1147 lines
31 KiB
JavaScript
1147 lines
31 KiB
JavaScript
import {
|
|
Ok,
|
|
Error,
|
|
toList,
|
|
Empty as $Empty,
|
|
prepend as listPrepend,
|
|
CustomType as $CustomType,
|
|
isEqual,
|
|
} from "../gleam.mjs";
|
|
import * as $int from "../gleam/int.mjs";
|
|
import * as $list from "../gleam/list.mjs";
|
|
import * as $option from "../gleam/option.mjs";
|
|
import { None, Some } from "../gleam/option.mjs";
|
|
import * as $string from "../gleam/string.mjs";
|
|
import * as $string_tree from "../gleam/string_tree.mjs";
|
|
import {
|
|
pop_codeunit,
|
|
string_codeunit_slice as codeunit_slice,
|
|
parse_query,
|
|
percent_encode,
|
|
percent_decode,
|
|
} from "../gleam_stdlib.mjs";
|
|
|
|
export { parse_query, percent_decode, percent_encode };
|
|
|
|
export class Uri extends $CustomType {
|
|
constructor(scheme, userinfo, host, port, path, query, fragment) {
|
|
super();
|
|
this.scheme = scheme;
|
|
this.userinfo = userinfo;
|
|
this.host = host;
|
|
this.port = port;
|
|
this.path = path;
|
|
this.query = query;
|
|
this.fragment = fragment;
|
|
}
|
|
}
|
|
export const Uri$Uri = (scheme, userinfo, host, port, path, query, fragment) =>
|
|
new Uri(scheme, userinfo, host, port, path, query, fragment);
|
|
export const Uri$isUri = (value) => value instanceof Uri;
|
|
export const Uri$Uri$scheme = (value) => value.scheme;
|
|
export const Uri$Uri$0 = (value) => value.scheme;
|
|
export const Uri$Uri$userinfo = (value) => value.userinfo;
|
|
export const Uri$Uri$1 = (value) => value.userinfo;
|
|
export const Uri$Uri$host = (value) => value.host;
|
|
export const Uri$Uri$2 = (value) => value.host;
|
|
export const Uri$Uri$port = (value) => value.port;
|
|
export const Uri$Uri$3 = (value) => value.port;
|
|
export const Uri$Uri$path = (value) => value.path;
|
|
export const Uri$Uri$4 = (value) => value.path;
|
|
export const Uri$Uri$query = (value) => value.query;
|
|
export const Uri$Uri$5 = (value) => value.query;
|
|
export const Uri$Uri$fragment = (value) => value.fragment;
|
|
export const Uri$Uri$6 = (value) => value.fragment;
|
|
|
|
function is_valid_host_within_brackets_char(char) {
|
|
return (((((48 >= char) && (char <= 57)) || ((65 >= char) && (char <= 90))) || ((97 >= char) && (char <= 122))) || (char === 58)) || (char === 46);
|
|
}
|
|
|
|
function parse_fragment(rest, pieces) {
|
|
return new Ok(
|
|
new Uri(
|
|
pieces.scheme,
|
|
pieces.userinfo,
|
|
pieces.host,
|
|
pieces.port,
|
|
pieces.path,
|
|
pieces.query,
|
|
new Some(rest),
|
|
),
|
|
);
|
|
}
|
|
|
|
function parse_query_with_question_mark_loop(
|
|
loop$original,
|
|
loop$uri_string,
|
|
loop$pieces,
|
|
loop$size
|
|
) {
|
|
while (true) {
|
|
let original = loop$original;
|
|
let uri_string = loop$uri_string;
|
|
let pieces = loop$pieces;
|
|
let size = loop$size;
|
|
if (uri_string.startsWith("#")) {
|
|
if (size === 0) {
|
|
let rest = uri_string.slice(1);
|
|
return parse_fragment(rest, pieces);
|
|
} else {
|
|
let rest = uri_string.slice(1);
|
|
let query = codeunit_slice(original, 0, size);
|
|
let pieces$1 = new Uri(
|
|
pieces.scheme,
|
|
pieces.userinfo,
|
|
pieces.host,
|
|
pieces.port,
|
|
pieces.path,
|
|
new Some(query),
|
|
pieces.fragment,
|
|
);
|
|
return parse_fragment(rest, pieces$1);
|
|
}
|
|
} else if (uri_string === "") {
|
|
return new Ok(
|
|
new Uri(
|
|
pieces.scheme,
|
|
pieces.userinfo,
|
|
pieces.host,
|
|
pieces.port,
|
|
pieces.path,
|
|
new Some(original),
|
|
pieces.fragment,
|
|
),
|
|
);
|
|
} else {
|
|
let $ = pop_codeunit(uri_string);
|
|
let rest;
|
|
rest = $[1];
|
|
loop$original = original;
|
|
loop$uri_string = rest;
|
|
loop$pieces = pieces;
|
|
loop$size = size + 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
function parse_query_with_question_mark(uri_string, pieces) {
|
|
return parse_query_with_question_mark_loop(uri_string, uri_string, pieces, 0);
|
|
}
|
|
|
|
function parse_path_loop(loop$original, loop$uri_string, loop$pieces, loop$size) {
|
|
while (true) {
|
|
let original = loop$original;
|
|
let uri_string = loop$uri_string;
|
|
let pieces = loop$pieces;
|
|
let size = loop$size;
|
|
if (uri_string.startsWith("?")) {
|
|
let rest = uri_string.slice(1);
|
|
let path = codeunit_slice(original, 0, size);
|
|
let pieces$1 = new Uri(
|
|
pieces.scheme,
|
|
pieces.userinfo,
|
|
pieces.host,
|
|
pieces.port,
|
|
path,
|
|
pieces.query,
|
|
pieces.fragment,
|
|
);
|
|
return parse_query_with_question_mark(rest, pieces$1);
|
|
} else if (uri_string.startsWith("#")) {
|
|
let rest = uri_string.slice(1);
|
|
let path = codeunit_slice(original, 0, size);
|
|
let pieces$1 = new Uri(
|
|
pieces.scheme,
|
|
pieces.userinfo,
|
|
pieces.host,
|
|
pieces.port,
|
|
path,
|
|
pieces.query,
|
|
pieces.fragment,
|
|
);
|
|
return parse_fragment(rest, pieces$1);
|
|
} else if (uri_string === "") {
|
|
return new Ok(
|
|
new Uri(
|
|
pieces.scheme,
|
|
pieces.userinfo,
|
|
pieces.host,
|
|
pieces.port,
|
|
original,
|
|
pieces.query,
|
|
pieces.fragment,
|
|
),
|
|
);
|
|
} else {
|
|
let $ = pop_codeunit(uri_string);
|
|
let rest;
|
|
rest = $[1];
|
|
loop$original = original;
|
|
loop$uri_string = rest;
|
|
loop$pieces = pieces;
|
|
loop$size = size + 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
function parse_path(uri_string, pieces) {
|
|
return parse_path_loop(uri_string, uri_string, pieces, 0);
|
|
}
|
|
|
|
function parse_port_loop(loop$uri_string, loop$pieces, loop$port) {
|
|
while (true) {
|
|
let uri_string = loop$uri_string;
|
|
let pieces = loop$pieces;
|
|
let port = loop$port;
|
|
if (uri_string.startsWith("0")) {
|
|
let rest = uri_string.slice(1);
|
|
loop$uri_string = rest;
|
|
loop$pieces = pieces;
|
|
loop$port = port * 10;
|
|
} else if (uri_string.startsWith("1")) {
|
|
let rest = uri_string.slice(1);
|
|
loop$uri_string = rest;
|
|
loop$pieces = pieces;
|
|
loop$port = port * 10 + 1;
|
|
} else if (uri_string.startsWith("2")) {
|
|
let rest = uri_string.slice(1);
|
|
loop$uri_string = rest;
|
|
loop$pieces = pieces;
|
|
loop$port = port * 10 + 2;
|
|
} else if (uri_string.startsWith("3")) {
|
|
let rest = uri_string.slice(1);
|
|
loop$uri_string = rest;
|
|
loop$pieces = pieces;
|
|
loop$port = port * 10 + 3;
|
|
} else if (uri_string.startsWith("4")) {
|
|
let rest = uri_string.slice(1);
|
|
loop$uri_string = rest;
|
|
loop$pieces = pieces;
|
|
loop$port = port * 10 + 4;
|
|
} else if (uri_string.startsWith("5")) {
|
|
let rest = uri_string.slice(1);
|
|
loop$uri_string = rest;
|
|
loop$pieces = pieces;
|
|
loop$port = port * 10 + 5;
|
|
} else if (uri_string.startsWith("6")) {
|
|
let rest = uri_string.slice(1);
|
|
loop$uri_string = rest;
|
|
loop$pieces = pieces;
|
|
loop$port = port * 10 + 6;
|
|
} else if (uri_string.startsWith("7")) {
|
|
let rest = uri_string.slice(1);
|
|
loop$uri_string = rest;
|
|
loop$pieces = pieces;
|
|
loop$port = port * 10 + 7;
|
|
} else if (uri_string.startsWith("8")) {
|
|
let rest = uri_string.slice(1);
|
|
loop$uri_string = rest;
|
|
loop$pieces = pieces;
|
|
loop$port = port * 10 + 8;
|
|
} else if (uri_string.startsWith("9")) {
|
|
let rest = uri_string.slice(1);
|
|
loop$uri_string = rest;
|
|
loop$pieces = pieces;
|
|
loop$port = port * 10 + 9;
|
|
} else if (uri_string.startsWith("?")) {
|
|
let rest = uri_string.slice(1);
|
|
let pieces$1 = new Uri(
|
|
pieces.scheme,
|
|
pieces.userinfo,
|
|
pieces.host,
|
|
new Some(port),
|
|
pieces.path,
|
|
pieces.query,
|
|
pieces.fragment,
|
|
);
|
|
return parse_query_with_question_mark(rest, pieces$1);
|
|
} else if (uri_string.startsWith("#")) {
|
|
let rest = uri_string.slice(1);
|
|
let pieces$1 = new Uri(
|
|
pieces.scheme,
|
|
pieces.userinfo,
|
|
pieces.host,
|
|
new Some(port),
|
|
pieces.path,
|
|
pieces.query,
|
|
pieces.fragment,
|
|
);
|
|
return parse_fragment(rest, pieces$1);
|
|
} else if (uri_string.startsWith("/")) {
|
|
let pieces$1 = new Uri(
|
|
pieces.scheme,
|
|
pieces.userinfo,
|
|
pieces.host,
|
|
new Some(port),
|
|
pieces.path,
|
|
pieces.query,
|
|
pieces.fragment,
|
|
);
|
|
return parse_path(uri_string, pieces$1);
|
|
} else if (uri_string === "") {
|
|
return new Ok(
|
|
new Uri(
|
|
pieces.scheme,
|
|
pieces.userinfo,
|
|
pieces.host,
|
|
new Some(port),
|
|
pieces.path,
|
|
pieces.query,
|
|
pieces.fragment,
|
|
),
|
|
);
|
|
} else {
|
|
return new Error(undefined);
|
|
}
|
|
}
|
|
}
|
|
|
|
function parse_port(uri_string, pieces) {
|
|
if (uri_string.startsWith(":0")) {
|
|
let rest = uri_string.slice(2);
|
|
return parse_port_loop(rest, pieces, 0);
|
|
} else if (uri_string.startsWith(":1")) {
|
|
let rest = uri_string.slice(2);
|
|
return parse_port_loop(rest, pieces, 1);
|
|
} else if (uri_string.startsWith(":2")) {
|
|
let rest = uri_string.slice(2);
|
|
return parse_port_loop(rest, pieces, 2);
|
|
} else if (uri_string.startsWith(":3")) {
|
|
let rest = uri_string.slice(2);
|
|
return parse_port_loop(rest, pieces, 3);
|
|
} else if (uri_string.startsWith(":4")) {
|
|
let rest = uri_string.slice(2);
|
|
return parse_port_loop(rest, pieces, 4);
|
|
} else if (uri_string.startsWith(":5")) {
|
|
let rest = uri_string.slice(2);
|
|
return parse_port_loop(rest, pieces, 5);
|
|
} else if (uri_string.startsWith(":6")) {
|
|
let rest = uri_string.slice(2);
|
|
return parse_port_loop(rest, pieces, 6);
|
|
} else if (uri_string.startsWith(":7")) {
|
|
let rest = uri_string.slice(2);
|
|
return parse_port_loop(rest, pieces, 7);
|
|
} else if (uri_string.startsWith(":8")) {
|
|
let rest = uri_string.slice(2);
|
|
return parse_port_loop(rest, pieces, 8);
|
|
} else if (uri_string.startsWith(":9")) {
|
|
let rest = uri_string.slice(2);
|
|
return parse_port_loop(rest, pieces, 9);
|
|
} else if (uri_string === ":") {
|
|
return new Ok(pieces);
|
|
} else if (uri_string === "") {
|
|
return new Ok(pieces);
|
|
} else if (uri_string.startsWith("?")) {
|
|
let rest = uri_string.slice(1);
|
|
return parse_query_with_question_mark(rest, pieces);
|
|
} else if (uri_string.startsWith(":?")) {
|
|
let rest = uri_string.slice(2);
|
|
return parse_query_with_question_mark(rest, pieces);
|
|
} else if (uri_string.startsWith("#")) {
|
|
let rest = uri_string.slice(1);
|
|
return parse_fragment(rest, pieces);
|
|
} else if (uri_string.startsWith(":#")) {
|
|
let rest = uri_string.slice(2);
|
|
return parse_fragment(rest, pieces);
|
|
} else if (uri_string.startsWith("/")) {
|
|
return parse_path(uri_string, pieces);
|
|
} else if (uri_string.startsWith(":")) {
|
|
let rest = uri_string.slice(1);
|
|
if (rest.startsWith("/")) {
|
|
return parse_path(rest, pieces);
|
|
} else {
|
|
return new Error(undefined);
|
|
}
|
|
} else {
|
|
return new Error(undefined);
|
|
}
|
|
}
|
|
|
|
function parse_host_outside_of_brackets_loop(
|
|
loop$original,
|
|
loop$uri_string,
|
|
loop$pieces,
|
|
loop$size
|
|
) {
|
|
while (true) {
|
|
let original = loop$original;
|
|
let uri_string = loop$uri_string;
|
|
let pieces = loop$pieces;
|
|
let size = loop$size;
|
|
if (uri_string === "") {
|
|
return new Ok(
|
|
new Uri(
|
|
pieces.scheme,
|
|
pieces.userinfo,
|
|
new Some(original),
|
|
pieces.port,
|
|
pieces.path,
|
|
pieces.query,
|
|
pieces.fragment,
|
|
),
|
|
);
|
|
} else if (uri_string.startsWith(":")) {
|
|
let host = codeunit_slice(original, 0, size);
|
|
let pieces$1 = new Uri(
|
|
pieces.scheme,
|
|
pieces.userinfo,
|
|
new Some(host),
|
|
pieces.port,
|
|
pieces.path,
|
|
pieces.query,
|
|
pieces.fragment,
|
|
);
|
|
return parse_port(uri_string, pieces$1);
|
|
} else if (uri_string.startsWith("/")) {
|
|
let host = codeunit_slice(original, 0, size);
|
|
let pieces$1 = new Uri(
|
|
pieces.scheme,
|
|
pieces.userinfo,
|
|
new Some(host),
|
|
pieces.port,
|
|
pieces.path,
|
|
pieces.query,
|
|
pieces.fragment,
|
|
);
|
|
return parse_path(uri_string, pieces$1);
|
|
} else if (uri_string.startsWith("?")) {
|
|
let rest = uri_string.slice(1);
|
|
let host = codeunit_slice(original, 0, size);
|
|
let pieces$1 = new Uri(
|
|
pieces.scheme,
|
|
pieces.userinfo,
|
|
new Some(host),
|
|
pieces.port,
|
|
pieces.path,
|
|
pieces.query,
|
|
pieces.fragment,
|
|
);
|
|
return parse_query_with_question_mark(rest, pieces$1);
|
|
} else if (uri_string.startsWith("#")) {
|
|
let rest = uri_string.slice(1);
|
|
let host = codeunit_slice(original, 0, size);
|
|
let pieces$1 = new Uri(
|
|
pieces.scheme,
|
|
pieces.userinfo,
|
|
new Some(host),
|
|
pieces.port,
|
|
pieces.path,
|
|
pieces.query,
|
|
pieces.fragment,
|
|
);
|
|
return parse_fragment(rest, pieces$1);
|
|
} else {
|
|
let $ = pop_codeunit(uri_string);
|
|
let rest;
|
|
rest = $[1];
|
|
loop$original = original;
|
|
loop$uri_string = rest;
|
|
loop$pieces = pieces;
|
|
loop$size = size + 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
function parse_host_within_brackets_loop(
|
|
loop$original,
|
|
loop$uri_string,
|
|
loop$pieces,
|
|
loop$size
|
|
) {
|
|
while (true) {
|
|
let original = loop$original;
|
|
let uri_string = loop$uri_string;
|
|
let pieces = loop$pieces;
|
|
let size = loop$size;
|
|
if (uri_string === "") {
|
|
return new Ok(
|
|
new Uri(
|
|
pieces.scheme,
|
|
pieces.userinfo,
|
|
new Some(uri_string),
|
|
pieces.port,
|
|
pieces.path,
|
|
pieces.query,
|
|
pieces.fragment,
|
|
),
|
|
);
|
|
} else if (uri_string.startsWith("]")) {
|
|
if (size === 0) {
|
|
let rest = uri_string.slice(1);
|
|
return parse_port(rest, pieces);
|
|
} else {
|
|
let rest = uri_string.slice(1);
|
|
let host = codeunit_slice(original, 0, size + 1);
|
|
let pieces$1 = new Uri(
|
|
pieces.scheme,
|
|
pieces.userinfo,
|
|
new Some(host),
|
|
pieces.port,
|
|
pieces.path,
|
|
pieces.query,
|
|
pieces.fragment,
|
|
);
|
|
return parse_port(rest, pieces$1);
|
|
}
|
|
} else if (uri_string.startsWith("/")) {
|
|
if (size === 0) {
|
|
return parse_path(uri_string, pieces);
|
|
} else {
|
|
let host = codeunit_slice(original, 0, size);
|
|
let pieces$1 = new Uri(
|
|
pieces.scheme,
|
|
pieces.userinfo,
|
|
new Some(host),
|
|
pieces.port,
|
|
pieces.path,
|
|
pieces.query,
|
|
pieces.fragment,
|
|
);
|
|
return parse_path(uri_string, pieces$1);
|
|
}
|
|
} else if (uri_string.startsWith("?")) {
|
|
if (size === 0) {
|
|
let rest = uri_string.slice(1);
|
|
return parse_query_with_question_mark(rest, pieces);
|
|
} else {
|
|
let rest = uri_string.slice(1);
|
|
let host = codeunit_slice(original, 0, size);
|
|
let pieces$1 = new Uri(
|
|
pieces.scheme,
|
|
pieces.userinfo,
|
|
new Some(host),
|
|
pieces.port,
|
|
pieces.path,
|
|
pieces.query,
|
|
pieces.fragment,
|
|
);
|
|
return parse_query_with_question_mark(rest, pieces$1);
|
|
}
|
|
} else if (uri_string.startsWith("#")) {
|
|
if (size === 0) {
|
|
let rest = uri_string.slice(1);
|
|
return parse_fragment(rest, pieces);
|
|
} else {
|
|
let rest = uri_string.slice(1);
|
|
let host = codeunit_slice(original, 0, size);
|
|
let pieces$1 = new Uri(
|
|
pieces.scheme,
|
|
pieces.userinfo,
|
|
new Some(host),
|
|
pieces.port,
|
|
pieces.path,
|
|
pieces.query,
|
|
pieces.fragment,
|
|
);
|
|
return parse_fragment(rest, pieces$1);
|
|
}
|
|
} else {
|
|
let $ = pop_codeunit(uri_string);
|
|
let char;
|
|
let rest;
|
|
char = $[0];
|
|
rest = $[1];
|
|
let $1 = is_valid_host_within_brackets_char(char);
|
|
if ($1) {
|
|
loop$original = original;
|
|
loop$uri_string = rest;
|
|
loop$pieces = pieces;
|
|
loop$size = size + 1;
|
|
} else {
|
|
return parse_host_outside_of_brackets_loop(
|
|
original,
|
|
original,
|
|
pieces,
|
|
0,
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function parse_host_within_brackets(uri_string, pieces) {
|
|
return parse_host_within_brackets_loop(uri_string, uri_string, pieces, 0);
|
|
}
|
|
|
|
function parse_host_outside_of_brackets(uri_string, pieces) {
|
|
return parse_host_outside_of_brackets_loop(uri_string, uri_string, pieces, 0);
|
|
}
|
|
|
|
function parse_host(uri_string, pieces) {
|
|
if (uri_string.startsWith("[")) {
|
|
return parse_host_within_brackets(uri_string, pieces);
|
|
} else if (uri_string.startsWith(":")) {
|
|
let pieces$1 = new Uri(
|
|
pieces.scheme,
|
|
pieces.userinfo,
|
|
new Some(""),
|
|
pieces.port,
|
|
pieces.path,
|
|
pieces.query,
|
|
pieces.fragment,
|
|
);
|
|
return parse_port(uri_string, pieces$1);
|
|
} else if (uri_string === "") {
|
|
return new Ok(
|
|
new Uri(
|
|
pieces.scheme,
|
|
pieces.userinfo,
|
|
new Some(""),
|
|
pieces.port,
|
|
pieces.path,
|
|
pieces.query,
|
|
pieces.fragment,
|
|
),
|
|
);
|
|
} else {
|
|
return parse_host_outside_of_brackets(uri_string, pieces);
|
|
}
|
|
}
|
|
|
|
function parse_userinfo_loop(
|
|
loop$original,
|
|
loop$uri_string,
|
|
loop$pieces,
|
|
loop$size
|
|
) {
|
|
while (true) {
|
|
let original = loop$original;
|
|
let uri_string = loop$uri_string;
|
|
let pieces = loop$pieces;
|
|
let size = loop$size;
|
|
if (uri_string.startsWith("@")) {
|
|
if (size === 0) {
|
|
let rest = uri_string.slice(1);
|
|
return parse_host(rest, pieces);
|
|
} else {
|
|
let rest = uri_string.slice(1);
|
|
let userinfo = codeunit_slice(original, 0, size);
|
|
let pieces$1 = new Uri(
|
|
pieces.scheme,
|
|
new Some(userinfo),
|
|
pieces.host,
|
|
pieces.port,
|
|
pieces.path,
|
|
pieces.query,
|
|
pieces.fragment,
|
|
);
|
|
return parse_host(rest, pieces$1);
|
|
}
|
|
} else if (uri_string === "") {
|
|
return parse_host(original, pieces);
|
|
} else if (uri_string.startsWith("/")) {
|
|
return parse_host(original, pieces);
|
|
} else if (uri_string.startsWith("?")) {
|
|
return parse_host(original, pieces);
|
|
} else if (uri_string.startsWith("#")) {
|
|
return parse_host(original, pieces);
|
|
} else {
|
|
let $ = pop_codeunit(uri_string);
|
|
let rest;
|
|
rest = $[1];
|
|
loop$original = original;
|
|
loop$uri_string = rest;
|
|
loop$pieces = pieces;
|
|
loop$size = size + 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
function parse_authority_pieces(string, pieces) {
|
|
return parse_userinfo_loop(string, string, pieces, 0);
|
|
}
|
|
|
|
function parse_authority_with_slashes(uri_string, pieces) {
|
|
if (uri_string === "//") {
|
|
return new Ok(
|
|
new Uri(
|
|
pieces.scheme,
|
|
pieces.userinfo,
|
|
new Some(""),
|
|
pieces.port,
|
|
pieces.path,
|
|
pieces.query,
|
|
pieces.fragment,
|
|
),
|
|
);
|
|
} else if (uri_string.startsWith("//")) {
|
|
let rest = uri_string.slice(2);
|
|
return parse_authority_pieces(rest, pieces);
|
|
} else {
|
|
return parse_path(uri_string, pieces);
|
|
}
|
|
}
|
|
|
|
function parse_scheme_loop(
|
|
loop$original,
|
|
loop$uri_string,
|
|
loop$pieces,
|
|
loop$size
|
|
) {
|
|
while (true) {
|
|
let original = loop$original;
|
|
let uri_string = loop$uri_string;
|
|
let pieces = loop$pieces;
|
|
let size = loop$size;
|
|
if (uri_string.startsWith("/")) {
|
|
if (size === 0) {
|
|
return parse_authority_with_slashes(uri_string, pieces);
|
|
} else {
|
|
let scheme = codeunit_slice(original, 0, size);
|
|
let pieces$1 = new Uri(
|
|
new Some($string.lowercase(scheme)),
|
|
pieces.userinfo,
|
|
pieces.host,
|
|
pieces.port,
|
|
pieces.path,
|
|
pieces.query,
|
|
pieces.fragment,
|
|
);
|
|
return parse_authority_with_slashes(uri_string, pieces$1);
|
|
}
|
|
} else if (uri_string.startsWith("?")) {
|
|
if (size === 0) {
|
|
let rest = uri_string.slice(1);
|
|
return parse_query_with_question_mark(rest, pieces);
|
|
} else {
|
|
let rest = uri_string.slice(1);
|
|
let scheme = codeunit_slice(original, 0, size);
|
|
let pieces$1 = new Uri(
|
|
new Some($string.lowercase(scheme)),
|
|
pieces.userinfo,
|
|
pieces.host,
|
|
pieces.port,
|
|
pieces.path,
|
|
pieces.query,
|
|
pieces.fragment,
|
|
);
|
|
return parse_query_with_question_mark(rest, pieces$1);
|
|
}
|
|
} else if (uri_string.startsWith("#")) {
|
|
if (size === 0) {
|
|
let rest = uri_string.slice(1);
|
|
return parse_fragment(rest, pieces);
|
|
} else {
|
|
let rest = uri_string.slice(1);
|
|
let scheme = codeunit_slice(original, 0, size);
|
|
let pieces$1 = new Uri(
|
|
new Some($string.lowercase(scheme)),
|
|
pieces.userinfo,
|
|
pieces.host,
|
|
pieces.port,
|
|
pieces.path,
|
|
pieces.query,
|
|
pieces.fragment,
|
|
);
|
|
return parse_fragment(rest, pieces$1);
|
|
}
|
|
} else if (uri_string.startsWith(":")) {
|
|
if (size === 0) {
|
|
return new Error(undefined);
|
|
} else {
|
|
let rest = uri_string.slice(1);
|
|
let scheme = codeunit_slice(original, 0, size);
|
|
let pieces$1 = new Uri(
|
|
new Some($string.lowercase(scheme)),
|
|
pieces.userinfo,
|
|
pieces.host,
|
|
pieces.port,
|
|
pieces.path,
|
|
pieces.query,
|
|
pieces.fragment,
|
|
);
|
|
return parse_authority_with_slashes(rest, pieces$1);
|
|
}
|
|
} else if (uri_string === "") {
|
|
return new Ok(
|
|
new Uri(
|
|
pieces.scheme,
|
|
pieces.userinfo,
|
|
pieces.host,
|
|
pieces.port,
|
|
original,
|
|
pieces.query,
|
|
pieces.fragment,
|
|
),
|
|
);
|
|
} else {
|
|
let $ = pop_codeunit(uri_string);
|
|
let rest;
|
|
rest = $[1];
|
|
loop$original = original;
|
|
loop$uri_string = rest;
|
|
loop$pieces = pieces;
|
|
loop$size = size + 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
function query_pair(pair) {
|
|
return $string_tree.from_strings(
|
|
toList([percent_encode(pair[0]), "=", percent_encode(pair[1])]),
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Encodes a list of key value pairs as a URI query string.
|
|
*
|
|
* The opposite operation is `uri.parse_query`.
|
|
*
|
|
* ## Examples
|
|
*
|
|
* ```gleam
|
|
* query_to_string([#("a", "1"), #("b", "2")])
|
|
* // -> "a=1&b=2"
|
|
* ```
|
|
*/
|
|
export function query_to_string(query) {
|
|
let _pipe = query;
|
|
let _pipe$1 = $list.map(_pipe, query_pair);
|
|
let _pipe$2 = $list.intersperse(_pipe$1, $string_tree.from_string("&"));
|
|
let _pipe$3 = $string_tree.concat(_pipe$2);
|
|
return $string_tree.to_string(_pipe$3);
|
|
}
|
|
|
|
function remove_dot_segments_loop(loop$input, loop$accumulator) {
|
|
while (true) {
|
|
let input = loop$input;
|
|
let accumulator = loop$accumulator;
|
|
if (input instanceof $Empty) {
|
|
return $list.reverse(accumulator);
|
|
} else {
|
|
let segment = input.head;
|
|
let rest = input.tail;
|
|
let _block;
|
|
if (segment === "") {
|
|
_block = accumulator;
|
|
} else if (segment === ".") {
|
|
_block = accumulator;
|
|
} else if (segment === "..") {
|
|
if (accumulator instanceof $Empty) {
|
|
_block = accumulator;
|
|
} else {
|
|
let accumulator$1 = accumulator.tail;
|
|
_block = accumulator$1;
|
|
}
|
|
} else {
|
|
let segment$1 = segment;
|
|
let accumulator$1 = accumulator;
|
|
_block = listPrepend(segment$1, accumulator$1);
|
|
}
|
|
let accumulator$1 = _block;
|
|
loop$input = rest;
|
|
loop$accumulator = accumulator$1;
|
|
}
|
|
}
|
|
}
|
|
|
|
function remove_dot_segments(input) {
|
|
return remove_dot_segments_loop(input, toList([]));
|
|
}
|
|
|
|
/**
|
|
* Splits the path section of a URI into it's constituent segments.
|
|
*
|
|
* Removes empty segments and resolves dot-segments as specified in
|
|
* [section 5.2](https://www.ietf.org/rfc/rfc3986.html#section-5.2) of the RFC.
|
|
*
|
|
* ## Examples
|
|
*
|
|
* ```gleam
|
|
* path_segments("/users/1")
|
|
* // -> ["users" ,"1"]
|
|
* ```
|
|
*/
|
|
export function path_segments(path) {
|
|
return remove_dot_segments($string.split(path, "/"));
|
|
}
|
|
|
|
/**
|
|
* Encodes a `Uri` value as a URI string.
|
|
*
|
|
* The opposite operation is `uri.parse`.
|
|
*
|
|
* ## Examples
|
|
*
|
|
* ```gleam
|
|
* let uri = Uri(..empty, scheme: Some("https"), host: Some("example.com"))
|
|
* to_string(uri)
|
|
* // -> "https://example.com"
|
|
* ```
|
|
*/
|
|
export function to_string(uri) {
|
|
let _block;
|
|
let $ = uri.fragment;
|
|
if ($ instanceof Some) {
|
|
let fragment = $[0];
|
|
_block = toList(["#", fragment]);
|
|
} else {
|
|
_block = toList([]);
|
|
}
|
|
let parts = _block;
|
|
let _block$1;
|
|
let $1 = uri.query;
|
|
if ($1 instanceof Some) {
|
|
let query = $1[0];
|
|
_block$1 = listPrepend("?", listPrepend(query, parts));
|
|
} else {
|
|
_block$1 = parts;
|
|
}
|
|
let parts$1 = _block$1;
|
|
let parts$2 = listPrepend(uri.path, parts$1);
|
|
let _block$2;
|
|
let $2 = uri.host;
|
|
let $3 = $string.starts_with(uri.path, "/");
|
|
if ($2 instanceof Some && !$3) {
|
|
let host = $2[0];
|
|
if (host !== "") {
|
|
_block$2 = listPrepend("/", parts$2);
|
|
} else {
|
|
_block$2 = parts$2;
|
|
}
|
|
} else {
|
|
_block$2 = parts$2;
|
|
}
|
|
let parts$3 = _block$2;
|
|
let _block$3;
|
|
let $4 = uri.host;
|
|
let $5 = uri.port;
|
|
if ($4 instanceof Some && $5 instanceof Some) {
|
|
let port = $5[0];
|
|
_block$3 = listPrepend(":", listPrepend($int.to_string(port), parts$3));
|
|
} else {
|
|
_block$3 = parts$3;
|
|
}
|
|
let parts$4 = _block$3;
|
|
let _block$4;
|
|
let $6 = uri.scheme;
|
|
let $7 = uri.userinfo;
|
|
let $8 = uri.host;
|
|
if ($6 instanceof Some) {
|
|
if ($7 instanceof Some) {
|
|
if ($8 instanceof Some) {
|
|
let s = $6[0];
|
|
let u = $7[0];
|
|
let h = $8[0];
|
|
_block$4 = listPrepend(
|
|
s,
|
|
listPrepend(
|
|
"://",
|
|
listPrepend(u, listPrepend("@", listPrepend(h, parts$4))),
|
|
),
|
|
);
|
|
} else {
|
|
let s = $6[0];
|
|
_block$4 = listPrepend(s, listPrepend(":", parts$4));
|
|
}
|
|
} else if ($8 instanceof Some) {
|
|
let s = $6[0];
|
|
let h = $8[0];
|
|
_block$4 = listPrepend(s, listPrepend("://", listPrepend(h, parts$4)));
|
|
} else {
|
|
let s = $6[0];
|
|
_block$4 = listPrepend(s, listPrepend(":", parts$4));
|
|
}
|
|
} else if ($7 instanceof None && $8 instanceof Some) {
|
|
let h = $8[0];
|
|
_block$4 = listPrepend("//", listPrepend(h, parts$4));
|
|
} else {
|
|
_block$4 = parts$4;
|
|
}
|
|
let parts$5 = _block$4;
|
|
return $string.concat(parts$5);
|
|
}
|
|
|
|
/**
|
|
* Fetches the origin of a URI.
|
|
*
|
|
* Returns the origin of a uri as defined in
|
|
* [RFC 6454](https://tools.ietf.org/html/rfc6454)
|
|
*
|
|
* The supported URI schemes are `http` and `https`.
|
|
* URLs without a scheme will return `Error`.
|
|
*
|
|
* ## Examples
|
|
*
|
|
* ```gleam
|
|
* let assert Ok(uri) = parse("https://example.com/path?foo#bar")
|
|
* origin(uri)
|
|
* // -> Ok("https://example.com")
|
|
* ```
|
|
*/
|
|
export function origin(uri) {
|
|
let scheme;
|
|
let host;
|
|
let port;
|
|
scheme = uri.scheme;
|
|
host = uri.host;
|
|
port = uri.port;
|
|
if (host instanceof Some && scheme instanceof Some) {
|
|
let $ = scheme[0];
|
|
if ($ === "https" && isEqual(port, new Some(443))) {
|
|
let h = host[0];
|
|
return new Ok($string.concat(toList(["https://", h])));
|
|
} else if ($ === "http" && isEqual(port, new Some(80))) {
|
|
let h = host[0];
|
|
return new Ok($string.concat(toList(["http://", h])));
|
|
} else {
|
|
let s = $;
|
|
if ((s === "http") || (s === "https")) {
|
|
let h = host[0];
|
|
if (port instanceof Some) {
|
|
let p = port[0];
|
|
return new Ok(
|
|
$string.concat(toList([s, "://", h, ":", $int.to_string(p)])),
|
|
);
|
|
} else {
|
|
return new Ok($string.concat(toList([s, "://", h])));
|
|
}
|
|
} else {
|
|
return new Error(undefined);
|
|
}
|
|
}
|
|
} else {
|
|
return new Error(undefined);
|
|
}
|
|
}
|
|
|
|
function drop_last(elements) {
|
|
return $list.take(elements, $list.length(elements) - 1);
|
|
}
|
|
|
|
function join_segments(segments) {
|
|
return $string.join(listPrepend("", segments), "/");
|
|
}
|
|
|
|
/**
|
|
* Resolves a URI with respect to the given base URI.
|
|
*
|
|
* The base URI must be an absolute URI or this function will return an error.
|
|
* The algorithm for merging uris is described in
|
|
* [RFC 3986](https://tools.ietf.org/html/rfc3986#section-5.2).
|
|
*/
|
|
export function merge(base, relative) {
|
|
let $ = base.scheme;
|
|
if ($ instanceof Some) {
|
|
let $1 = base.host;
|
|
if ($1 instanceof Some) {
|
|
let $2 = relative.host;
|
|
if ($2 instanceof Some) {
|
|
let _block;
|
|
let _pipe = relative.path;
|
|
let _pipe$1 = $string.split(_pipe, "/");
|
|
let _pipe$2 = remove_dot_segments(_pipe$1);
|
|
_block = join_segments(_pipe$2);
|
|
let path = _block;
|
|
let resolved = new Uri(
|
|
$option.or(relative.scheme, base.scheme),
|
|
new None(),
|
|
relative.host,
|
|
$option.or(relative.port, base.port),
|
|
path,
|
|
relative.query,
|
|
relative.fragment,
|
|
);
|
|
return new Ok(resolved);
|
|
} else {
|
|
let _block;
|
|
let $4 = relative.path;
|
|
if ($4 === "") {
|
|
_block = [base.path, $option.or(relative.query, base.query)];
|
|
} else {
|
|
let _block$1;
|
|
let $5 = $string.starts_with(relative.path, "/");
|
|
if ($5) {
|
|
_block$1 = $string.split(relative.path, "/");
|
|
} else {
|
|
let _pipe = base.path;
|
|
let _pipe$1 = $string.split(_pipe, "/");
|
|
let _pipe$2 = drop_last(_pipe$1);
|
|
_block$1 = $list.append(_pipe$2, $string.split(relative.path, "/"));
|
|
}
|
|
let path_segments$1 = _block$1;
|
|
let _block$2;
|
|
let _pipe = path_segments$1;
|
|
let _pipe$1 = remove_dot_segments(_pipe);
|
|
_block$2 = join_segments(_pipe$1);
|
|
let path = _block$2;
|
|
_block = [path, relative.query];
|
|
}
|
|
let $3 = _block;
|
|
let new_path;
|
|
let new_query;
|
|
new_path = $3[0];
|
|
new_query = $3[1];
|
|
let resolved = new Uri(
|
|
base.scheme,
|
|
new None(),
|
|
base.host,
|
|
base.port,
|
|
new_path,
|
|
new_query,
|
|
relative.fragment,
|
|
);
|
|
return new Ok(resolved);
|
|
}
|
|
} else {
|
|
return new Error(undefined);
|
|
}
|
|
} else {
|
|
return new Error(undefined);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Constant representing an empty URI, equivalent to "".
|
|
*
|
|
* ## Examples
|
|
*
|
|
* ```gleam
|
|
* let uri = Uri(..empty, scheme: Some("https"), host: Some("example.com"))
|
|
* // -> Uri(
|
|
* // scheme: Some("https"),
|
|
* // userinfo: None,
|
|
* // host: Some("example.com"),
|
|
* // port: None,
|
|
* // path: "",
|
|
* // query: None,
|
|
* // fragment: None,
|
|
* // )
|
|
* ```
|
|
*/
|
|
export const empty = /* @__PURE__ */ new Uri(
|
|
/* @__PURE__ */ new None(),
|
|
/* @__PURE__ */ new None(),
|
|
/* @__PURE__ */ new None(),
|
|
/* @__PURE__ */ new None(),
|
|
"",
|
|
/* @__PURE__ */ new None(),
|
|
/* @__PURE__ */ new None(),
|
|
);
|
|
|
|
/**
|
|
* Parses a compliant URI string into the `Uri` Type.
|
|
* If the string is not a valid URI string then an error is returned.
|
|
*
|
|
* The opposite operation is `uri.to_string`.
|
|
*
|
|
* ## Examples
|
|
*
|
|
* ```gleam
|
|
* parse("https://example.com:1234/a/b?query=true#fragment")
|
|
* // -> Ok(
|
|
* // Uri(
|
|
* // scheme: Some("https"),
|
|
* // userinfo: None,
|
|
* // host: Some("example.com"),
|
|
* // port: Some(1234),
|
|
* // path: "/a/b",
|
|
* // query: Some("query=true"),
|
|
* // fragment: Some("fragment")
|
|
* // )
|
|
* // )
|
|
* ```
|
|
*/
|
|
export function parse(uri_string) {
|
|
return parse_scheme_loop(uri_string, uri_string, empty, 0);
|
|
}
|