Last active
November 7, 2023 22:47
-
-
Save vane/1249e8cf8a8e5532af26a6c33df35c9f to your computer and use it in GitHub Desktop.
openresty call script read stdout and return as response
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- test.py - set absolute path | |
-- functions | |
local function write_error(data) | |
ngx.status = 500 | |
ngx.say('<h1>CGI response error</h1>') | |
ngx.say(data) | |
ngx.exit(ngx.OK) | |
end | |
local function write_body(headers, res) | |
local ss, ee = headers:find('([^&&]+)') | |
if ee == nil then | |
ngx.status = 404 | |
ngx.say(res) | |
return ngx.exit(ngx.OK) | |
end | |
ngx.status = tonumber(headers:sub(ss, ee)) | |
for header in headers:sub(ee+2):gmatch('([^&&]+)') do | |
local s, e = header:find('([^:]+)') | |
ngx.header[header:sub(s, e)] = header:sub(e+2) | |
end | |
local body = res:gsub('^\n?[^\n]*\n', '') | |
ngx.say(body) | |
ngx.exit(ngx.OK) | |
end | |
local function read_body() | |
ngx.req.read_body() | |
local raw_body = ngx.req.get_body_data() | |
if raw_body == nil then | |
local file = ngx.req.get_body_file() | |
if file == nil then | |
return '' | |
end | |
return file | |
end | |
-- if not content_type header starts with text then encode_base64 | |
local content_type = ngx.req.get_headers().content_type | |
if content_type:find('text', 1, true) == 1 or content_type:find('application/json', 1, true) == 1 then | |
return raw_body:gsub('"', '\\\\"'):gsub("'", "\\\\'") | |
end | |
return ngx.encode_base64(raw_body) | |
end | |
-- logic | |
local raw_header = ngx.req.raw_header() | |
local raw_body = read_body() | |
-- todo read path and store executable in redis | |
local ps = io.popen("python3 test.py '" ..raw_header.. "' " ..raw_body) | |
local res = ps:read("*a") | |
ps:close() | |
if res == nil then | |
return write_error(res) | |
end | |
-- read headers - 200&&key1:value1&&key2:value2\n | |
local headers = res:match('([^\n]*)\n?') | |
if headers == nil then | |
return write_error(raw_header) | |
end | |
return write_body(headers, res) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
server { | |
listen 443 ssl; | |
access_log /usr/local/openresty/nginx/logs/fn.example.com.log; | |
server_name fn.example.com; | |
ssl_certificate_by_lua_block { | |
auto_ssl:ssl_certificate(); | |
} | |
ssl_certificate /etc/ssl/resty-auto-ssl-fallback.crt; | |
ssl_certificate_key /etc/ssl/resty-auto-ssl-fallback.key; | |
location / { | |
# set absolute path | |
content_by_lua_file cgi.lua; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
# -*- coding: utf-8 -*- | |
import sys | |
import traceback | |
from http.server import BaseHTTPRequestHandler | |
from io import BytesIO | |
class Request(BaseHTTPRequestHandler): | |
def __init__(self, request_text): | |
self.rfile = BytesIO(request_text.encode('utf-8')) | |
self.raw_requestline = self.rfile.readline() | |
self.error_code = None | |
self.error_message = None | |
self.parse_request() | |
def send_error(self, code, message=None, explain=None): | |
self.error_code = code | |
self.error_message = message | |
def serve_image() -> None: | |
sys.stdout.buffer.write(b'200&&Content-Type:image/png\n') | |
with open('test.png', 'rb') as f: | |
sys.stdout.buffer.write(f.read()) | |
def print_request(req: Request) -> None: | |
sys.stdout.buffer.write(b'404&&Content-Type:text/html&&custom:test\n') | |
print(f'''<html><body> | |
<div><h3>headers keys</h3><pre>{req.headers.keys()}</pre></div> | |
<div><h3>host</h3><pre>{req.headers.get('host')}</pre></div> | |
<div><h3>raw args</h3><pre>{sys.argv[1:]}</pre></div> | |
</html></body>''') | |
if __name__ == '__main__': | |
# write headers -- important !!! new line at end | |
req = Request(sys.argv[1]) | |
try: | |
if req.path.startswith('/test.png'): | |
serve_image() | |
else: | |
print_request(req) | |
except: | |
sys.stdout.buffer.write(b'500&&Content-Type:text/html\n') | |
print('<div>problem<div>') | |
print(f'<div>{sys.argv[1:]}</div>') | |
print(f'<div><pre>{traceback.format_exc()}</pre></div>') |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment