summaryrefslogtreecommitdiff
path: root/js
diff options
context:
space:
mode:
Diffstat (limited to 'js')
-rw-r--r--js/fetch.ts87
-rw-r--r--js/fetch_test.ts31
-rw-r--r--js/headers.ts9
3 files changed, 109 insertions, 18 deletions
diff --git a/js/fetch.ts b/js/fetch.ts
index bd50cdfdc..636bbba10 100644
--- a/js/fetch.ts
+++ b/js/fetch.ts
@@ -1,5 +1,5 @@
// Copyright 2018 the Deno authors. All rights reserved. MIT license.
-import { assert, log, createResolvable, notImplemented } from "./util";
+import { assert, createResolvable, notImplemented } from "./util";
import * as flatbuffers from "./flatbuffers";
import { sendAsync } from "./dispatch";
import * as msg from "gen/msg_generated";
@@ -162,19 +162,73 @@ class Response implements domTypes.Response {
}
}
+function msgHttpRequest(
+ builder: flatbuffers.Builder,
+ url: string,
+ method: null | string,
+ headers: null | domTypes.Headers
+): flatbuffers.Offset {
+ const methodOffset = !method ? -1 : builder.createString(method);
+ let fieldsOffset: flatbuffers.Offset = -1;
+ const urlOffset = builder.createString(url);
+ if (headers) {
+ const kvOffsets: flatbuffers.Offset[] = [];
+ for (const [key, val] of headers.entries()) {
+ const keyOffset = builder.createString(key);
+ const valOffset = builder.createString(val);
+ msg.KeyValue.startKeyValue(builder);
+ msg.KeyValue.addKey(builder, keyOffset);
+ msg.KeyValue.addValue(builder, valOffset);
+ kvOffsets.push(msg.KeyValue.endKeyValue(builder));
+ }
+ fieldsOffset = msg.HttpHeader.createFieldsVector(builder, kvOffsets);
+ } else {
+ }
+ msg.HttpHeader.startHttpHeader(builder);
+ msg.HttpHeader.addIsRequest(builder, true);
+ msg.HttpHeader.addUrl(builder, urlOffset);
+ if (methodOffset >= 0) {
+ msg.HttpHeader.addMethod(builder, methodOffset);
+ }
+ if (fieldsOffset >= 0) {
+ msg.HttpHeader.addFields(builder, fieldsOffset);
+ }
+ return msg.HttpHeader.endHttpHeader(builder);
+}
+
/** Fetch a resource from the network. */
export async function fetch(
- input?: domTypes.Request | string,
+ input: domTypes.Request | string,
init?: domTypes.RequestInit
): Promise<Response> {
- const url = input as string;
- log("dispatch FETCH_REQ", url);
+ let url: string;
+ let method: string | null = null;
+ let headers: domTypes.Headers | null = null;
+
+ if (typeof input === "string") {
+ url = input;
+ if (init != null) {
+ method = init.method || null;
+ if (init.headers) {
+ headers =
+ init.headers instanceof Headers
+ ? init.headers
+ : new Headers(init.headers);
+ } else {
+ headers = null;
+ }
+ }
+ } else {
+ url = input.url;
+ method = input.method;
+ headers = input.headers;
+ }
// Send Fetch message
const builder = flatbuffers.createBuilder();
- const url_ = builder.createString(url);
+ const headerOff = msgHttpRequest(builder, url, method, headers);
msg.Fetch.startFetch(builder);
- msg.Fetch.addUrl(builder, url_);
+ msg.Fetch.addHeader(builder, headerOff);
const resBase = await sendAsync(
builder,
msg.Any.Fetch,
@@ -186,17 +240,22 @@ export async function fetch(
const inner = new msg.FetchRes();
assert(resBase.inner(inner) != null);
- const status = inner.status();
+ const header = inner.header()!;
const bodyRid = inner.bodyRid();
+ assert(!header.isRequest());
+ const status = header.status();
- const headersList: Array<[string, string]> = [];
- const len = inner.headerKeyLength();
- for (let i = 0; i < len; ++i) {
- const key = inner.headerKey(i);
- const value = inner.headerValue(i);
- headersList.push([key, value]);
- }
+ const headersList = deserializeHeaderFields(header);
const response = new Response(status, headersList, bodyRid);
return response;
}
+
+function deserializeHeaderFields(m: msg.HttpHeader): Array<[string, string]> {
+ const out: Array<[string, string]> = [];
+ for (let i = 0; i < m.fieldsLength(); i++) {
+ const item = m.fields(i)!;
+ out.push([item.key()!, item.value()!]);
+ }
+ return out;
+}
diff --git a/js/fetch_test.ts b/js/fetch_test.ts
index 0c60efb9d..8fad8da75 100644
--- a/js/fetch_test.ts
+++ b/js/fetch_test.ts
@@ -46,3 +46,34 @@ testPerm({ net: true }, async function responseClone() {
assertEqual(ab[i], ab1[i]);
}
});
+
+testPerm({ net: true }, async function fetchRequest() {
+ const addr = "127.0.0.1:4501";
+ const listener = deno.listen("tcp", addr);
+ const buf = new deno.Buffer();
+ listener.accept().then(async conn => {
+ buf.readFrom(conn);
+ await conn.write(
+ new TextEncoder().encode(
+ "HTTP/1.0 404 Not Found\r\nContent-Length: 2\r\n\r\nNF"
+ )
+ );
+ conn.close();
+ });
+ const response = await fetch(`http://${addr}/blah`, {
+ method: "POST",
+ headers: [["Hello", "World"], ["Foo", "Bar"]]
+ });
+ listener.close();
+ assertEqual(response.status, 404);
+ assertEqual(response.headers.get("Content-Length"), "2");
+
+ const actual = new TextDecoder().decode(buf.bytes());
+ const expected = [
+ "POST /blah HTTP/1.1\r\n",
+ "hello: World\r\n",
+ "foo: Bar\r\n",
+ `host: ${addr}\r\n\r\n`
+ ].join("");
+ assertEqual(actual, expected);
+});
diff --git a/js/headers.ts b/js/headers.ts
index 6892b0ef2..1b47ac7d3 100644
--- a/js/headers.ts
+++ b/js/headers.ts
@@ -79,7 +79,8 @@ class HeadersBase {
// @internal
// tslint:disable-next-line:variable-name
-export const Headers = DomIterableMixin<string, string, typeof HeadersBase>(
- HeadersBase,
- headerMap
-);
+export class Headers extends DomIterableMixin<
+ string,
+ string,
+ typeof HeadersBase
+>(HeadersBase, headerMap) {}