* @this {TCPConnection} * @param {!ArrayBuffer} data
(data)
| 69 | * @param {!ArrayBuffer} data |
| 70 | */ |
| 71 | async function on_data_http(data) |
| 72 | { |
| 73 | this.read = this.read || ""; |
| 74 | this.read += new TextDecoder().decode(data); |
| 75 | if(this.read && this.read.indexOf("\r\n\r\n") !== -1) { |
| 76 | let offset = this.read.indexOf("\r\n\r\n"); |
| 77 | let headers = this.read.substring(0, offset).split(/\r\n/); |
| 78 | let data = this.read.substring(offset + 4); |
| 79 | this.read = ""; |
| 80 | |
| 81 | let first_line = headers[0].split(" "); |
| 82 | let target; |
| 83 | if(/^https?:/.test(first_line[1])) { |
| 84 | // HTTP proxy |
| 85 | target = new URL(first_line[1]); |
| 86 | } |
| 87 | else { |
| 88 | target = new URL("http://host" + first_line[1]); |
| 89 | } |
| 90 | if(typeof window !== "undefined" && target.protocol === "http:" && window.location.protocol === "https:") { |
| 91 | // fix "Mixed Content" errors |
| 92 | target.protocol = "https:"; |
| 93 | } |
| 94 | |
| 95 | let req_headers = new Headers(); |
| 96 | for(let i = 1; i < headers.length; ++i) { |
| 97 | const header = this.net.parse_http_header(headers[i]); |
| 98 | if(!header) { |
| 99 | console.warn('The request contains an invalid header: "%s"', headers[i]); |
| 100 | this.write(new TextEncoder().encode("HTTP/1.1 400 Bad Request\r\nContent-Length: 0")); |
| 101 | return; |
| 102 | } |
| 103 | if( header.key.toLowerCase() === "host" ) target.host = header.value; |
| 104 | else req_headers.append(header.key, header.value); |
| 105 | } |
| 106 | |
| 107 | dbg_log("HTTP Dispatch: " + target.href, LOG_FETCH); |
| 108 | this.name = target.href; |
| 109 | let opts = { |
| 110 | method: first_line[0], |
| 111 | headers: req_headers, |
| 112 | }; |
| 113 | if(["put", "post"].indexOf(opts.method.toLowerCase()) !== -1) { |
| 114 | opts.body = data; |
| 115 | } |
| 116 | |
| 117 | const fetch_url = this.net.cors_proxy ? this.net.cors_proxy + encodeURIComponent(target.href) : target.href; |
| 118 | const encoder = new TextEncoder(); |
| 119 | let response_started = false; |
| 120 | this.net.fetch(fetch_url, opts).then((resp) => { |
| 121 | const header_lines = [ |
| 122 | `HTTP/1.1 ${resp.status} ${resp.statusText}`, |
| 123 | `x-was-fetch-redirected: ${!!resp.redirected}`, |
| 124 | `x-fetch-resp-url: ${resp.url}`, |
| 125 | "Connection: closed" |
| 126 | ]; |
| 127 | for(const [key, value] of resp.headers.entries()) { |
| 128 | if(!["content-encoding", "connection", "content-length", "transfer-encoding"].includes(key.toLowerCase())) { |