-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
1,017 additions
and
0 deletions.
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
#!/usr/bin/env python3 | ||
|
||
"""A simple HTTP server that forwards all requests to another server, adding CORS headers. | ||
Don't use this in production as it is not optimized for performance! | ||
""" | ||
|
||
from http.server import BaseHTTPRequestHandler, HTTPServer | ||
from socketserver import ThreadingMixIn | ||
from urllib import request | ||
from urllib.error import HTTPError | ||
|
||
|
||
class ThreadedHTTPServer(ThreadingMixIn, HTTPServer): | ||
"""Handle requests in a separate thread.""" | ||
daemon_threads = True # Optional: Set True to make the threads exit when the main thread does. | ||
|
||
|
||
class CORSProxyHTTPRequestHandler(BaseHTTPRequestHandler): | ||
def do_REQUEST(self, method): | ||
target_url = self.path[1:] # Remove the leading '/' | ||
|
||
if not is_url_allowed(target_url): | ||
self.send_response(403) | ||
self.end_headers() | ||
self.wfile.write(b"403 Forbidden") | ||
return | ||
|
||
content_length = int(self.headers.get('Content-Length', 0)) | ||
body = self.rfile.read(content_length) if content_length else None | ||
headers = {key: val for (key, val) in self.headers.items() if key.lower() not in ('host', 'connection', 'content-length', 'content-type')} | ||
|
||
try: | ||
req = request.Request(target_url, data=body, headers=headers, method=method) | ||
with request.urlopen(req) as response: | ||
self.send_response(response.status) | ||
|
||
# Set up response headers, excluding the Access-Control-Allow-Origin header | ||
for header, value in response.headers.items(): | ||
if header.lower() != 'access-control-allow-origin': | ||
self.send_header(header, value) | ||
|
||
# Replace the Access-Control-Allow-Origin header with our own | ||
self.send_header('Access-Control-Allow-Origin', '*') | ||
|
||
self.end_headers() | ||
self.wfile.write(response.read()) | ||
except Exception as e: | ||
if isinstance(e, HTTPError): | ||
# Make sure to send the original status code from the upstream server | ||
self.send_response(e.code) | ||
# Copy headers from the HTTPError object | ||
for header, value in e.headers.items(): | ||
if header.lower() != 'access-control-allow-origin': | ||
self.send_header(header, value) | ||
else: | ||
self.send_response(500) | ||
|
||
# Include Access-Control-Allow-Origin in case of an exception too | ||
self.send_header('Access-Control-Allow-Origin', '*') | ||
self.end_headers() | ||
|
||
if isinstance(e, HTTPError): | ||
# Copy the response body from the HTTPError object | ||
self.wfile.write(e.read()) | ||
else: | ||
# Sending a text response containing the error message | ||
response_text = str(e) if isinstance(e, HTTPError) else 'Internal Server Error' | ||
self.wfile.write(response_text.encode()) | ||
|
||
|
||
def do_HEAD(self): | ||
self.do_REQUEST('HEAD') | ||
|
||
def do_GET(self): | ||
self.do_REQUEST('GET') | ||
|
||
def do_POST(self): | ||
self.do_REQUEST('POST') | ||
|
||
def do_PUT(self): | ||
self.do_REQUEST('PUT') | ||
|
||
def do_DELETE(self): | ||
self.do_REQUEST('DELETE') | ||
|
||
def do_OPTIONS(self): | ||
self.do_REQUEST('OPTIONS') | ||
|
||
|
||
def is_url_allowed(url): | ||
return True | ||
|
||
|
||
def run(server_class=ThreadedHTTPServer, handler_class=CORSProxyHTTPRequestHandler, port=8080): | ||
server_address = ('', port) | ||
httpd = server_class(server_address, handler_class) | ||
print(f"CORS proxy server listening on port {port}") | ||
httpd.serve_forever() | ||
|
||
|
||
if __name__ == '__main__': | ||
run(port=3000) |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
/* tslint:disable */ | ||
/* eslint-disable */ | ||
/** | ||
*/ | ||
export function start(): void; | ||
/** | ||
* Get the version of the runtime. | ||
* @returns {Promise<string>} | ||
*/ | ||
export function version(): Promise<string>; | ||
/** | ||
* Run a script. | ||
* | ||
* # Arguments | ||
* - `args` - a list of arguments to pass to the runtime, including the script name and arguments. | ||
* | ||
* # Example | ||
* | ||
* ```js | ||
* const result = await run(["phatjs", "-c", "console.log(scriptArgs)", "--", "Hello, world!"]); | ||
* console.log(result); | ||
* ``` | ||
* @param {(string)[]} args | ||
* @returns {Promise<any>} | ||
*/ | ||
export function run(args: (string)[]): Promise<any>; | ||
/** | ||
* Set a hook for the runtime. | ||
* | ||
* # Available hooks | ||
* - `fetch` - a function that takes a `Request` object and returns a `Response` object. | ||
* @param {string} hook_name | ||
* @param {any} hook_value | ||
*/ | ||
export function setHook(hook_name: string, hook_value: any): void; | ||
|
||
export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module; | ||
|
||
export interface InitOutput { | ||
readonly memory: WebAssembly.Memory; | ||
readonly start: () => void; | ||
readonly version: () => number; | ||
readonly run: (a: number, b: number) => number; | ||
readonly setHook: (a: number, b: number, c: number, d: number) => void; | ||
readonly __main_argc_argv: (a: number, b: number) => number; | ||
readonly __pink_malloc: (a: number) => number; | ||
readonly __pink_free: (a: number) => void; | ||
readonly __pink_realloc: (a: number, b: number) => number; | ||
readonly __pink_getrandom: (a: number, b: number) => void; | ||
readonly __pink_clock_time_get: (a: number, b: number, c: number) => number; | ||
readonly __pink_fd_write: (a: number, b: number, c: number) => number; | ||
readonly __wbindgen_malloc_command_export: (a: number, b: number) => number; | ||
readonly __wbindgen_realloc_command_export: (a: number, b: number, c: number, d: number) => number; | ||
readonly __wbindgen_export_2: WebAssembly.Table; | ||
readonly wasm_bindgen__convert__closures__invoke1_mut__h8c16b6c39c56dff5: (a: number, b: number, c: number) => void; | ||
readonly __wbindgen_exn_store_command_export: (a: number) => void; | ||
readonly wasm_bindgen__convert__closures__invoke2_mut__h1ea04ca8ac623e4b: (a: number, b: number, c: number, d: number) => void; | ||
readonly __wbindgen_add_to_stack_pointer: (a: number) => number; | ||
readonly __wbindgen_start: () => void; | ||
} | ||
|
||
export type SyncInitInput = BufferSource | WebAssembly.Module; | ||
/** | ||
* Instantiates the given `module`, which can either be bytes or | ||
* a precompiled `WebAssembly.Module`. | ||
* | ||
* @param {SyncInitInput} module | ||
* | ||
* @returns {InitOutput} | ||
*/ | ||
export function initSync(module: SyncInitInput): InitOutput; | ||
|
||
/** | ||
* If `module_or_path` is {RequestInfo} or {URL}, makes a request and | ||
* for everything else, calls `WebAssembly.instantiate` directly. | ||
* | ||
* @param {InitInput | Promise<InitInput>} module_or_path | ||
* | ||
* @returns {Promise<InitOutput>} | ||
*/ | ||
export default function __wbg_init (module_or_path?: InitInput | Promise<InitInput>): Promise<InitOutput>; |
Oops, something went wrong.