goscript 0.1.1 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cmd/goscript/cmd-test.go +104 -11
- package/cmd/goscript/cmd-test_test.go +1 -1
- package/cmd/goscript/cmd_compile.go +9 -0
- package/compiler/compile-request.go +31 -0
- package/compiler/compiler.go +1 -1
- package/compiler/compliance_test.go +0 -2
- package/compiler/config.go +2 -0
- package/compiler/gotest/package-result.go +2 -0
- package/compiler/gotest/request.go +85 -20
- package/compiler/gotest/runner.go +733 -96
- package/compiler/gotest/runner_test.go +647 -3
- package/compiler/lowered-program.go +10 -2
- package/compiler/lowering.go +2676 -349
- package/compiler/override-facts.go +77 -27
- package/compiler/override-registry.go +5 -4
- package/compiler/override-registry_test.go +178 -0
- package/compiler/package-graph_test.go +62 -7
- package/compiler/package-test-graph-variant.go +40 -16
- package/compiler/package-test-graph.go +0 -5
- package/compiler/package-test-graph_test.go +61 -3
- package/compiler/runtime-contract.go +40 -0
- package/compiler/semantic-model-types.go +16 -0
- package/compiler/semantic-model.go +336 -91
- package/compiler/semantic-model_test.go +50 -1
- package/compiler/service.go +9 -3
- package/compiler/skeleton_test.go +2371 -296
- package/compiler/tsworkspace/owner-process-unix_test.go +72 -0
- package/compiler/tsworkspace/owner.go +8 -0
- package/compiler/tsworkspace/tool-process-other.go +14 -0
- package/compiler/tsworkspace/tool-process-unix.go +19 -0
- package/compiler/typescript-emitter.go +149 -10
- package/dist/gs/builtin/builtin.d.ts +20 -1
- package/dist/gs/builtin/builtin.js +246 -26
- package/dist/gs/builtin/builtin.js.map +1 -1
- package/dist/gs/builtin/channel.d.ts +24 -10
- package/dist/gs/builtin/channel.js +143 -34
- package/dist/gs/builtin/channel.js.map +1 -1
- package/dist/gs/builtin/defer.d.ts +1 -0
- package/dist/gs/builtin/defer.js +12 -2
- package/dist/gs/builtin/defer.js.map +1 -1
- package/dist/gs/builtin/hostio.d.ts +9 -0
- package/dist/gs/builtin/hostio.js +25 -0
- package/dist/gs/builtin/hostio.js.map +1 -1
- package/dist/gs/builtin/map.js +40 -6
- package/dist/gs/builtin/map.js.map +1 -1
- package/dist/gs/builtin/print.js.map +1 -1
- package/dist/gs/builtin/slice.d.ts +43 -9
- package/dist/gs/builtin/slice.js +437 -234
- package/dist/gs/builtin/slice.js.map +1 -1
- package/dist/gs/builtin/type.d.ts +2 -0
- package/dist/gs/builtin/type.js +55 -10
- package/dist/gs/builtin/type.js.map +1 -1
- package/dist/gs/builtin/varRef.d.ts +2 -0
- package/dist/gs/builtin/varRef.js.map +1 -1
- package/dist/gs/bytes/buffer.gs.js +28 -28
- package/dist/gs/bytes/buffer.gs.js.map +1 -1
- package/dist/gs/bytes/bytes.gs.d.ts +7 -5
- package/dist/gs/bytes/bytes.gs.js +10 -4
- package/dist/gs/bytes/bytes.gs.js.map +1 -1
- package/dist/gs/bytes/iter.gs.js +13 -13
- package/dist/gs/bytes/iter.gs.js.map +1 -1
- package/dist/gs/compress/zlib/index.d.ts +26 -0
- package/dist/gs/compress/zlib/index.js +168 -0
- package/dist/gs/compress/zlib/index.js.map +1 -0
- package/dist/gs/context/context.d.ts +1 -1
- package/dist/gs/context/context.js +8 -3
- package/dist/gs/context/context.js.map +1 -1
- package/dist/gs/crypto/ecdh/index.d.ts +52 -0
- package/dist/gs/crypto/ecdh/index.js +226 -0
- package/dist/gs/crypto/ecdh/index.js.map +1 -0
- package/dist/gs/crypto/ed25519/index.d.ts +34 -0
- package/dist/gs/crypto/ed25519/index.js +160 -0
- package/dist/gs/crypto/ed25519/index.js.map +1 -0
- package/dist/gs/crypto/internal/constanttime/index.d.ts +4 -0
- package/dist/gs/crypto/internal/constanttime/index.js +18 -0
- package/dist/gs/crypto/internal/constanttime/index.js.map +1 -0
- package/dist/gs/crypto/rand/index.d.ts +2 -0
- package/dist/gs/crypto/rand/index.js +85 -0
- package/dist/gs/crypto/rand/index.js.map +1 -1
- package/dist/gs/crypto/sha1/index.d.ts +5 -0
- package/dist/gs/crypto/sha1/index.js +106 -0
- package/dist/gs/crypto/sha1/index.js.map +1 -0
- package/dist/gs/crypto/sha256/index.d.ts +8 -0
- package/dist/gs/crypto/sha256/index.js +118 -0
- package/dist/gs/crypto/sha256/index.js.map +1 -0
- package/dist/gs/crypto/sha512/index.d.ts +14 -0
- package/dist/gs/crypto/sha512/index.js +129 -0
- package/dist/gs/crypto/sha512/index.js.map +1 -0
- package/dist/gs/encoding/json/index.d.ts +3 -0
- package/dist/gs/encoding/json/index.js +15 -0
- package/dist/gs/encoding/json/index.js.map +1 -1
- package/dist/gs/errors/errors.js +29 -6
- package/dist/gs/errors/errors.js.map +1 -1
- package/dist/gs/fmt/fmt.d.ts +1 -1
- package/dist/gs/fmt/fmt.js +64 -3
- package/dist/gs/fmt/fmt.js.map +1 -1
- package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.d.ts +7 -7
- package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.js +52 -18
- package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.js.map +1 -1
- package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/json/index.js +56 -20
- package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/json/index.js.map +1 -1
- package/dist/gs/github.com/aperturerobotics/starpc/srpc/index.d.ts +57 -3
- package/dist/gs/github.com/aperturerobotics/starpc/srpc/index.js +366 -1
- package/dist/gs/github.com/aperturerobotics/starpc/srpc/index.js.map +1 -1
- package/dist/gs/github.com/aperturerobotics/util/conc/index.d.ts +20 -0
- package/dist/gs/github.com/aperturerobotics/util/conc/index.js +134 -0
- package/dist/gs/github.com/aperturerobotics/util/conc/index.js.map +1 -0
- package/dist/gs/github.com/aperturerobotics/wasivm/wazero/kernel/runtime/browser/browser.js.map +1 -1
- package/dist/gs/github.com/hack-pad/safejs/internal/catch/index.d.ts +3 -0
- package/dist/gs/github.com/hack-pad/safejs/internal/catch/index.js +50 -0
- package/dist/gs/github.com/hack-pad/safejs/internal/catch/index.js.map +1 -0
- package/dist/gs/github.com/klauspost/compress/internal/le/index.js +3 -2
- package/dist/gs/github.com/klauspost/compress/internal/le/index.js.map +1 -1
- package/dist/gs/github.com/mr-tron/base58/base58/index.d.ts +27 -0
- package/dist/gs/github.com/mr-tron/base58/base58/index.js +172 -0
- package/dist/gs/github.com/mr-tron/base58/base58/index.js.map +1 -0
- package/dist/gs/github.com/zeebo/blake3/internal/consts/index.d.ts +21 -0
- package/dist/gs/github.com/zeebo/blake3/internal/consts/index.js +22 -0
- package/dist/gs/github.com/zeebo/blake3/internal/consts/index.js.map +1 -0
- package/dist/gs/go/token/index.js +11 -4
- package/dist/gs/go/token/index.js.map +1 -1
- package/dist/gs/hash/fnv/index.d.ts +57 -0
- package/dist/gs/hash/fnv/index.js +299 -0
- package/dist/gs/hash/fnv/index.js.map +1 -0
- package/dist/gs/hash/index.d.ts +17 -0
- package/dist/gs/hash/index.js +94 -0
- package/dist/gs/hash/index.js.map +1 -0
- package/dist/gs/io/fs/readlink.js +2 -6
- package/dist/gs/io/fs/readlink.js.map +1 -1
- package/dist/gs/io/fs/walk.js.map +1 -1
- package/dist/gs/io/io.d.ts +8 -5
- package/dist/gs/io/io.js +20 -2
- package/dist/gs/io/io.js.map +1 -1
- package/dist/gs/iter/iter.d.ts +3 -2
- package/dist/gs/iter/iter.js.map +1 -1
- package/dist/gs/maps/iter.d.ts +5 -5
- package/dist/gs/maps/iter.js +48 -21
- package/dist/gs/maps/iter.js.map +1 -1
- package/dist/gs/maps/maps.d.ts +6 -6
- package/dist/gs/math/bits/index.js +14 -24
- package/dist/gs/math/bits/index.js.map +1 -1
- package/dist/gs/mime/index.js +3 -1
- package/dist/gs/mime/index.js.map +1 -1
- package/dist/gs/net/http/httptest/index.d.ts +20 -1
- package/dist/gs/net/http/httptest/index.js +85 -3
- package/dist/gs/net/http/httptest/index.js.map +1 -1
- package/dist/gs/net/http/index.d.ts +118 -6
- package/dist/gs/net/http/index.js +389 -14
- package/dist/gs/net/http/index.js.map +1 -1
- package/dist/gs/net/http/pprof/index.d.ts +8 -0
- package/dist/gs/net/http/pprof/index.js +59 -0
- package/dist/gs/net/http/pprof/index.js.map +1 -0
- package/dist/gs/os/error.gs.js +9 -7
- package/dist/gs/os/error.gs.js.map +1 -1
- package/dist/gs/os/types_js.gs.js +95 -15
- package/dist/gs/os/types_js.gs.js.map +1 -1
- package/dist/gs/os/zero_copy_posix.gs.js +1 -1
- package/dist/gs/os/zero_copy_posix.gs.js.map +1 -1
- package/dist/gs/path/filepath/match.js.map +1 -1
- package/dist/gs/path/filepath/path.d.ts +5 -3
- package/dist/gs/path/filepath/path.js +65 -10
- package/dist/gs/path/filepath/path.js.map +1 -1
- package/dist/gs/reflect/index.d.ts +3 -2
- package/dist/gs/reflect/index.js +2 -1
- package/dist/gs/reflect/index.js.map +1 -1
- package/dist/gs/reflect/iter.js +2 -2
- package/dist/gs/reflect/iter.js.map +1 -1
- package/dist/gs/reflect/map.js +26 -0
- package/dist/gs/reflect/map.js.map +1 -1
- package/dist/gs/reflect/type.d.ts +24 -5
- package/dist/gs/reflect/type.js +390 -38
- package/dist/gs/reflect/type.js.map +1 -1
- package/dist/gs/reflect/types.d.ts +1 -0
- package/dist/gs/reflect/types.js +3 -1
- package/dist/gs/reflect/types.js.map +1 -1
- package/dist/gs/reflect/value.d.ts +4 -1
- package/dist/gs/reflect/value.js +39 -1
- package/dist/gs/reflect/value.js.map +1 -1
- package/dist/gs/reflect/visiblefields.js +1 -1
- package/dist/gs/reflect/visiblefields.js.map +1 -1
- package/dist/gs/runtime/debug/index.d.ts +39 -0
- package/dist/gs/runtime/debug/index.js +58 -0
- package/dist/gs/runtime/debug/index.js.map +1 -1
- package/dist/gs/runtime/pprof/index.d.ts +20 -0
- package/dist/gs/runtime/pprof/index.js +85 -0
- package/dist/gs/runtime/pprof/index.js.map +1 -0
- package/dist/gs/runtime/trace/index.d.ts +19 -0
- package/dist/gs/runtime/trace/index.js +64 -0
- package/dist/gs/runtime/trace/index.js.map +1 -0
- package/dist/gs/slices/slices.d.ts +24 -9
- package/dist/gs/slices/slices.js +229 -24
- package/dist/gs/slices/slices.js.map +1 -1
- package/dist/gs/sort/slice.gs.d.ts +5 -3
- package/dist/gs/sort/slice.gs.js +55 -17
- package/dist/gs/sort/slice.gs.js.map +1 -1
- package/dist/gs/strings/builder.js +26 -17
- package/dist/gs/strings/builder.js.map +1 -1
- package/dist/gs/strings/iter.js +140 -75
- package/dist/gs/strings/iter.js.map +1 -1
- package/dist/gs/strings/replace.js +2 -2
- package/dist/gs/strings/replace.js.map +1 -1
- package/dist/gs/strings/strings.js +52 -6
- package/dist/gs/strings/strings.js.map +1 -1
- package/dist/gs/sync/sync.d.ts +6 -3
- package/dist/gs/sync/sync.js +39 -11
- package/dist/gs/sync/sync.js.map +1 -1
- package/dist/gs/syscall/errors.d.ts +116 -112
- package/dist/gs/syscall/errors.js +38 -1
- package/dist/gs/syscall/errors.js.map +1 -1
- package/dist/gs/syscall/fs.d.ts +2 -8
- package/dist/gs/syscall/fs.js.map +1 -1
- package/dist/gs/syscall/js/index.js +20 -12
- package/dist/gs/syscall/js/index.js.map +1 -1
- package/dist/gs/syscall/types.d.ts +4 -1
- package/dist/gs/syscall/types.js.map +1 -1
- package/dist/gs/testing/testing.d.ts +4 -3
- package/dist/gs/testing/testing.js +21 -4
- package/dist/gs/testing/testing.js.map +1 -1
- package/dist/gs/time/time.js +22 -0
- package/dist/gs/time/time.js.map +1 -1
- package/dist/gs/unicode/unicode.js.map +1 -1
- package/dist/gs/unique/index.js +7 -2
- package/dist/gs/unique/index.js.map +1 -1
- package/go.mod +8 -8
- package/go.sum +14 -23
- package/gs/builtin/builtin.ts +364 -37
- package/gs/builtin/channel.ts +208 -38
- package/gs/builtin/defer.ts +13 -2
- package/gs/builtin/hostio.test.ts +1 -0
- package/gs/builtin/hostio.ts +38 -0
- package/gs/builtin/map.ts +46 -6
- package/gs/builtin/print.ts +12 -3
- package/gs/builtin/runtime-contract.test.ts +290 -10
- package/gs/builtin/slice.test.ts +70 -0
- package/gs/builtin/slice.ts +566 -255
- package/gs/builtin/type.ts +63 -10
- package/gs/builtin/varRef.ts +2 -0
- package/gs/bytes/buffer.gs.ts +28 -28
- package/gs/bytes/bytes.gs.ts +19 -10
- package/gs/bytes/bytes.test.ts +17 -0
- package/gs/bytes/iter.gs.ts +13 -14
- package/gs/compress/zlib/index.test.ts +28 -0
- package/gs/compress/zlib/index.ts +200 -0
- package/gs/compress/zlib/meta.json +3 -0
- package/gs/context/context.test.ts +36 -2
- package/gs/context/context.ts +9 -4
- package/gs/crypto/ecdh/index.test.ts +43 -0
- package/gs/crypto/ecdh/index.ts +274 -0
- package/gs/crypto/ed25519/index.test.ts +41 -0
- package/gs/crypto/ed25519/index.ts +238 -0
- package/gs/crypto/ed25519/meta.json +13 -0
- package/gs/crypto/internal/constanttime/index.test.ts +25 -0
- package/gs/crypto/internal/constanttime/index.ts +22 -0
- package/gs/crypto/rand/index.test.ts +89 -1
- package/gs/crypto/rand/index.ts +103 -1
- package/gs/crypto/rand/meta.json +4 -1
- package/gs/crypto/sha1/index.test.ts +28 -0
- package/gs/crypto/sha1/index.ts +130 -0
- package/gs/crypto/sha1/meta.json +8 -0
- package/gs/crypto/sha256/index.test.ts +78 -0
- package/gs/crypto/sha256/index.ts +150 -0
- package/gs/crypto/sha256/meta.json +9 -0
- package/gs/crypto/sha512/index.test.ts +31 -0
- package/gs/crypto/sha512/index.ts +161 -0
- package/gs/crypto/sha512/meta.json +11 -0
- package/gs/encoding/json/index.test.ts +25 -3
- package/gs/encoding/json/index.ts +21 -3
- package/gs/errors/errors.test.ts +4 -1
- package/gs/errors/errors.ts +32 -8
- package/gs/fmt/fmt.test.ts +23 -1
- package/gs/fmt/fmt.ts +76 -10
- package/gs/github.com/aperturerobotics/protobuf-go-lite/index.test.ts +62 -7
- package/gs/github.com/aperturerobotics/protobuf-go-lite/index.ts +78 -36
- package/gs/github.com/aperturerobotics/protobuf-go-lite/json/index.test.ts +32 -11
- package/gs/github.com/aperturerobotics/protobuf-go-lite/json/index.ts +122 -43
- package/gs/github.com/aperturerobotics/starpc/srpc/index.test.ts +31 -0
- package/gs/github.com/aperturerobotics/starpc/srpc/index.ts +518 -4
- package/gs/github.com/aperturerobotics/starpc/srpc/meta.json +6 -0
- package/gs/github.com/aperturerobotics/util/conc/index.test.ts +30 -0
- package/gs/github.com/aperturerobotics/util/conc/index.ts +172 -0
- package/gs/github.com/aperturerobotics/util/conc/meta.json +9 -0
- package/gs/github.com/aperturerobotics/wasivm/wazero/kernel/runtime/browser/browser.ts +1 -4
- package/gs/github.com/hack-pad/safejs/internal/catch/index.test.ts +35 -0
- package/gs/github.com/hack-pad/safejs/internal/catch/index.ts +65 -0
- package/gs/github.com/hack-pad/safejs/internal/catch/meta.json +9 -0
- package/gs/github.com/klauspost/compress/internal/le/index.test.ts +2 -1
- package/gs/github.com/klauspost/compress/internal/le/index.ts +6 -5
- package/gs/github.com/mr-tron/base58/base58/index.test.ts +70 -0
- package/gs/github.com/mr-tron/base58/base58/index.ts +231 -0
- package/gs/github.com/mr-tron/base58/base58/meta.json +3 -0
- package/gs/github.com/zeebo/blake3/internal/consts/index.test.ts +46 -0
- package/gs/github.com/zeebo/blake3/internal/consts/index.ts +26 -0
- package/gs/go/token/index.ts +17 -4
- package/gs/hash/fnv/index.test.ts +67 -0
- package/gs/hash/fnv/index.ts +351 -0
- package/gs/hash/fnv/meta.json +3 -0
- package/gs/hash/index.test.ts +37 -0
- package/gs/hash/index.ts +118 -0
- package/gs/hash/meta.json +5 -0
- package/gs/internal/byteorder/index.test.ts +6 -6
- package/gs/io/fs/readlink.ts +40 -48
- package/gs/io/fs/walk.ts +10 -2
- package/gs/io/io.test.ts +64 -0
- package/gs/io/io.ts +34 -13
- package/gs/iter/iter.ts +8 -2
- package/gs/maps/iter.ts +69 -26
- package/gs/maps/maps.test.ts +23 -0
- package/gs/maps/maps.ts +6 -6
- package/gs/math/bits/index.test.ts +20 -0
- package/gs/math/bits/index.ts +15 -28
- package/gs/mime/index.ts +8 -2
- package/gs/net/http/httptest/index.test.ts +85 -0
- package/gs/net/http/httptest/index.ts +113 -3
- package/gs/net/http/index.test.ts +159 -1
- package/gs/net/http/index.ts +515 -15
- package/gs/net/http/meta.json +6 -0
- package/gs/net/http/pprof/index.test.ts +47 -0
- package/gs/net/http/pprof/index.ts +65 -0
- package/gs/os/error.gs.ts +9 -10
- package/gs/os/error.test.ts +41 -0
- package/gs/os/file_unix_js.test.ts +55 -0
- package/gs/os/tempfile.gs.test.ts +37 -10
- package/gs/os/types_js.gs.ts +94 -15
- package/gs/os/zero_copy_posix.gs.ts +1 -2
- package/gs/path/filepath/match.ts +4 -1
- package/gs/path/filepath/meta.json +6 -0
- package/gs/path/filepath/path.test.ts +57 -2
- package/gs/path/filepath/path.ts +91 -12
- package/gs/reflect/field.test.ts +63 -0
- package/gs/reflect/index.ts +4 -1
- package/gs/reflect/iter.ts +2 -2
- package/gs/reflect/map.test.ts +24 -2
- package/gs/reflect/map.ts +35 -0
- package/gs/reflect/type.ts +543 -60
- package/gs/reflect/typefor.test.ts +100 -0
- package/gs/reflect/types.ts +3 -1
- package/gs/reflect/value.ts +50 -1
- package/gs/reflect/visiblefields.ts +1 -1
- package/gs/runtime/debug/index.test.ts +22 -1
- package/gs/runtime/debug/index.ts +88 -0
- package/gs/runtime/pprof/index.test.ts +36 -0
- package/gs/runtime/pprof/index.ts +104 -0
- package/gs/runtime/pprof/meta.json +6 -0
- package/gs/runtime/trace/index.test.ts +45 -0
- package/gs/runtime/trace/index.ts +97 -0
- package/gs/runtime/trace/meta.json +7 -0
- package/gs/slices/meta.json +2 -1
- package/gs/slices/slices.test.ts +86 -0
- package/gs/slices/slices.ts +284 -37
- package/gs/sort/slice.gs.ts +73 -23
- package/gs/sort/slice.test.ts +40 -0
- package/gs/strings/builder.test.ts +8 -0
- package/gs/strings/builder.ts +29 -17
- package/gs/strings/iter.test.ts +5 -7
- package/gs/strings/iter.ts +146 -71
- package/gs/strings/replace.test.ts +1 -4
- package/gs/strings/replace.ts +6 -6
- package/gs/strings/strings.test.ts +4 -0
- package/gs/strings/strings.ts +54 -6
- package/gs/sync/meta.json +1 -0
- package/gs/sync/sync.test.ts +57 -1
- package/gs/sync/sync.ts +45 -13
- package/gs/syscall/errors.ts +158 -115
- package/gs/syscall/fs.ts +8 -8
- package/gs/syscall/js/index.ts +49 -22
- package/gs/syscall/net.test.ts +26 -0
- package/gs/syscall/types.ts +7 -2
- package/gs/testing/testing.test.ts +56 -0
- package/gs/testing/testing.ts +27 -10
- package/gs/time/meta.json +2 -2
- package/gs/time/time.test.ts +4 -0
- package/gs/time/time.ts +33 -2
- package/gs/unicode/unicode.test.ts +14 -3
- package/gs/unicode/unicode.ts +1 -5
- package/gs/unique/index.ts +9 -2
- package/package.json +3 -3
package/gs/net/http/index.ts
CHANGED
|
@@ -1,53 +1,253 @@
|
|
|
1
1
|
import * as $ from '@goscript/builtin/index.js'
|
|
2
|
+
import * as bytes from '@goscript/bytes/index.js'
|
|
3
|
+
import * as context from '@goscript/context/index.js'
|
|
2
4
|
import * as errors from '@goscript/errors/index.js'
|
|
5
|
+
import * as fs from '@goscript/io/fs/fs.js'
|
|
3
6
|
import * as io from '@goscript/io/index.js'
|
|
7
|
+
import * as time from '@goscript/time/index.js'
|
|
4
8
|
|
|
5
9
|
export const StatusOK = 200
|
|
10
|
+
export const StatusCreated = 201
|
|
11
|
+
export const StatusPartialContent = 206
|
|
12
|
+
export const StatusMovedPermanently = 301
|
|
13
|
+
export const StatusBadRequest = 400
|
|
14
|
+
export const StatusUnauthorized = 401
|
|
15
|
+
export const StatusForbidden = 403
|
|
16
|
+
export const StatusMethodNotAllowed = 405
|
|
17
|
+
export const StatusRequestTimeout = 408
|
|
18
|
+
export const StatusConflict = 409
|
|
19
|
+
export const StatusNotFound = 404
|
|
20
|
+
export const StatusUnsupportedMediaType = 415
|
|
21
|
+
export const StatusTeapot = 418
|
|
22
|
+
export const StatusTooManyRequests = 429
|
|
23
|
+
export const StatusRequestedRangeNotSatisfiable = 416
|
|
24
|
+
export const StatusInternalServerError = 500
|
|
25
|
+
export const StatusServiceUnavailable = 503
|
|
26
|
+
|
|
27
|
+
export const MethodGet = 'GET'
|
|
28
|
+
export const MethodPost = 'POST'
|
|
29
|
+
export const MethodDelete = 'DELETE'
|
|
30
|
+
|
|
31
|
+
export const ErrNotSupported = errors.New('feature not supported')
|
|
32
|
+
export const ServerContextKey = Symbol('net/http ServerContextKey')
|
|
6
33
|
|
|
7
34
|
export function StatusText(code: number): string {
|
|
8
35
|
switch (code) {
|
|
9
36
|
case StatusOK:
|
|
10
37
|
return 'OK'
|
|
38
|
+
case StatusMovedPermanently:
|
|
39
|
+
return 'Moved Permanently'
|
|
40
|
+
case StatusUnauthorized:
|
|
41
|
+
return 'Unauthorized'
|
|
42
|
+
case StatusForbidden:
|
|
43
|
+
return 'Forbidden'
|
|
44
|
+
case StatusMethodNotAllowed:
|
|
45
|
+
return 'Method Not Allowed'
|
|
46
|
+
case StatusBadRequest:
|
|
47
|
+
return 'Bad Request'
|
|
48
|
+
case StatusRequestTimeout:
|
|
49
|
+
return 'Request Timeout'
|
|
50
|
+
case StatusConflict:
|
|
51
|
+
return 'Conflict'
|
|
52
|
+
case StatusNotFound:
|
|
53
|
+
return 'Not Found'
|
|
54
|
+
case StatusUnsupportedMediaType:
|
|
55
|
+
return 'Unsupported Media Type'
|
|
56
|
+
case StatusTooManyRequests:
|
|
57
|
+
return 'Too Many Requests'
|
|
58
|
+
case StatusPartialContent:
|
|
59
|
+
return 'Partial Content'
|
|
60
|
+
case StatusRequestedRangeNotSatisfiable:
|
|
61
|
+
return 'Requested Range Not Satisfiable'
|
|
62
|
+
case StatusTeapot:
|
|
63
|
+
return "I'm a teapot"
|
|
64
|
+
case StatusInternalServerError:
|
|
65
|
+
return 'Internal Server Error'
|
|
66
|
+
case StatusServiceUnavailable:
|
|
67
|
+
return 'Service Unavailable'
|
|
11
68
|
default:
|
|
12
69
|
return ''
|
|
13
70
|
}
|
|
14
71
|
}
|
|
15
72
|
|
|
16
|
-
export
|
|
73
|
+
export type Header = Map<string, $.Slice<string>>
|
|
74
|
+
|
|
75
|
+
export const Header = Map as {
|
|
76
|
+
new(entries?: Iterable<readonly [string, $.Slice<string>]> | null): Header
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export function Header_Add(h: Header, key: string, value: string): void {
|
|
80
|
+
key = canonicalMIMEHeaderKey(key)
|
|
81
|
+
const values = Array.from(h.get(key) ?? [])
|
|
82
|
+
values.push(value)
|
|
83
|
+
h.set(key, $.arrayToSlice(values))
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export function Header_Del(h: Header, key: string): void {
|
|
87
|
+
h.delete(canonicalMIMEHeaderKey(key))
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export function Header_Get(h: Header, key: string): string {
|
|
91
|
+
const values = h.get(canonicalMIMEHeaderKey(key))
|
|
92
|
+
return values == null || values.length === 0 ? '' : String(values[0])
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export function Header_Set(h: Header, key: string, value: string): void {
|
|
96
|
+
h.set(canonicalMIMEHeaderKey(key), $.arrayToSlice([value]))
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function canonicalMIMEHeaderKey(key: string): string {
|
|
100
|
+
let upper = true
|
|
101
|
+
let out = ''
|
|
102
|
+
for (let i = 0; i < key.length; i++) {
|
|
103
|
+
const ch = key[i]
|
|
104
|
+
if (ch === '-') {
|
|
105
|
+
upper = true
|
|
106
|
+
out += ch
|
|
107
|
+
continue
|
|
108
|
+
}
|
|
109
|
+
out += upper ? ch.toUpperCase() : ch.toLowerCase()
|
|
110
|
+
upper = false
|
|
111
|
+
}
|
|
112
|
+
return out
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
class QueryValues extends Map<string, $.Slice<string>> {
|
|
17
116
|
public Add(key: string, value: string): void {
|
|
18
117
|
const values = Array.from(this.get(key) ?? [])
|
|
19
118
|
values.push(value)
|
|
20
119
|
this.set(key, $.arrayToSlice(values))
|
|
21
120
|
}
|
|
22
121
|
|
|
23
|
-
public Del(key: string): void {
|
|
24
|
-
this.delete(key)
|
|
25
|
-
}
|
|
26
|
-
|
|
27
122
|
public Get(key: string): string {
|
|
28
123
|
const values = this.get(key)
|
|
29
124
|
return values == null || values.length === 0 ? '' : String(values[0])
|
|
30
125
|
}
|
|
31
126
|
|
|
32
|
-
public
|
|
33
|
-
|
|
127
|
+
public Encode(): string {
|
|
128
|
+
const params = new URLSearchParams()
|
|
129
|
+
for (const [key, values] of this.entries()) {
|
|
130
|
+
for (const value of Array.from(values ?? [])) {
|
|
131
|
+
params.append(key, String(value))
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
return params.toString()
|
|
34
135
|
}
|
|
35
136
|
}
|
|
36
137
|
|
|
37
|
-
|
|
38
|
-
|
|
138
|
+
class RequestURL {
|
|
139
|
+
public Scheme: string
|
|
140
|
+
public Host: string
|
|
141
|
+
public Path: string
|
|
142
|
+
public RawQuery: string
|
|
143
|
+
|
|
144
|
+
constructor(path: string, rawQuery: string, scheme = '', host = '') {
|
|
145
|
+
this.Scheme = scheme
|
|
146
|
+
this.Host = host
|
|
147
|
+
this.Path = path
|
|
148
|
+
this.RawQuery = rawQuery
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
public Query(): QueryValues {
|
|
152
|
+
const values = new QueryValues()
|
|
153
|
+
const params = new URLSearchParams(this.RawQuery)
|
|
154
|
+
params.forEach((value, key) => values.Add(key, value))
|
|
155
|
+
return values
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
public clone(): RequestURL {
|
|
159
|
+
return new RequestURL(this.Path, this.RawQuery, this.Scheme, this.Host)
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
public String(): string {
|
|
163
|
+
const query = this.RawQuery === '' ? '' : `?${this.RawQuery}`
|
|
164
|
+
const path = this.Path === '' ? '/' : this.Path
|
|
165
|
+
if (this.Scheme === '' || this.Host === '') {
|
|
166
|
+
return `${path}${query}`
|
|
167
|
+
}
|
|
168
|
+
return `${this.Scheme}://${this.Host}${path}${query}`
|
|
169
|
+
}
|
|
39
170
|
}
|
|
40
171
|
|
|
41
|
-
|
|
42
|
-
|
|
172
|
+
function parseRequestURL(rawURL: string): RequestURL {
|
|
173
|
+
try {
|
|
174
|
+
const parsed = new URL(rawURL, 'http://goscript.invalid')
|
|
175
|
+
const hasHost = /^[a-zA-Z][a-zA-Z0-9+.-]*:\/\//.test(rawURL)
|
|
176
|
+
return new RequestURL(
|
|
177
|
+
parsed.pathname,
|
|
178
|
+
parsed.search.startsWith('?') ? parsed.search.slice(1) : parsed.search,
|
|
179
|
+
hasHost ? parsed.protocol.replace(/:$/, '') : '',
|
|
180
|
+
hasHost ? parsed.host : '',
|
|
181
|
+
)
|
|
182
|
+
} catch {
|
|
183
|
+
return new RequestURL('', '')
|
|
184
|
+
}
|
|
43
185
|
}
|
|
44
186
|
|
|
45
|
-
|
|
46
|
-
|
|
187
|
+
class responseBody implements io.ReadCloser {
|
|
188
|
+
private reader: bytes.Reader
|
|
189
|
+
|
|
190
|
+
constructor(data: $.Bytes) {
|
|
191
|
+
this.reader = bytes.NewReader(Uint8Array.from(data ?? []))
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
public Read(p: $.Bytes): [number, $.GoError] {
|
|
195
|
+
return this.reader.Read(p)
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
public Close(): $.GoError {
|
|
199
|
+
return null
|
|
200
|
+
}
|
|
47
201
|
}
|
|
48
202
|
|
|
49
|
-
|
|
50
|
-
|
|
203
|
+
class memoryResponseWriter implements ResponseWriter {
|
|
204
|
+
public Code = StatusOK
|
|
205
|
+
public Body = new bytes.Buffer()
|
|
206
|
+
private headerMap = new Header()
|
|
207
|
+
private wroteHeader = false
|
|
208
|
+
|
|
209
|
+
public Header(): Header {
|
|
210
|
+
return this.headerMap
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
public Write(p: $.Slice<number>): [number, $.GoError] {
|
|
214
|
+
if (!this.wroteHeader) {
|
|
215
|
+
this.WriteHeader(StatusOK)
|
|
216
|
+
}
|
|
217
|
+
return this.Body.Write(p)
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
public WriteHeader(statusCode: number): void {
|
|
221
|
+
if (this.wroteHeader) {
|
|
222
|
+
return
|
|
223
|
+
}
|
|
224
|
+
this.wroteHeader = true
|
|
225
|
+
this.Code = statusCode
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
public Result(): Response {
|
|
229
|
+
return new Response({
|
|
230
|
+
Body: new responseBody(this.Body.Bytes()),
|
|
231
|
+
Header: this.headerMap,
|
|
232
|
+
StatusCode: this.Code,
|
|
233
|
+
})
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
const inProcessServers = new Map<string, Handler>()
|
|
238
|
+
let nextInProcessServerID = 1
|
|
239
|
+
|
|
240
|
+
export function RegisterInProcessServer(handler: Handler | null): string {
|
|
241
|
+
const host = `goscript-httptest-${nextInProcessServerID++}.invalid`
|
|
242
|
+
inProcessServers.set(host, handler ?? { ServeHTTP: NotFound })
|
|
243
|
+
return `http://${host}`
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
export function UnregisterInProcessServer(rawURL: string): void {
|
|
247
|
+
const parsed = parseRequestURL(rawURL)
|
|
248
|
+
if (parsed.Host !== '') {
|
|
249
|
+
inProcessServers.delete(parsed.Host)
|
|
250
|
+
}
|
|
51
251
|
}
|
|
52
252
|
|
|
53
253
|
export interface ResponseWriter {
|
|
@@ -56,26 +256,326 @@ export interface ResponseWriter {
|
|
|
56
256
|
WriteHeader(statusCode: number): void
|
|
57
257
|
}
|
|
58
258
|
|
|
259
|
+
export class Request {
|
|
260
|
+
public Method: string
|
|
261
|
+
public URL: any
|
|
262
|
+
public Body: io.Reader | null
|
|
263
|
+
public Header: Header
|
|
264
|
+
public ContentLength: number
|
|
265
|
+
public RequestURI: string
|
|
266
|
+
public RemoteAddr: string
|
|
267
|
+
private ctx: context.Context
|
|
268
|
+
|
|
269
|
+
constructor(init?: Partial<Request> & { ctx?: context.Context }) {
|
|
270
|
+
this.Method = init?.Method ?? ''
|
|
271
|
+
this.URL = init?.URL ?? null
|
|
272
|
+
this.Body = init?.Body ?? null
|
|
273
|
+
this.Header = init?.Header ?? new Header()
|
|
274
|
+
this.ContentLength = init?.ContentLength ?? 0
|
|
275
|
+
this.RequestURI = init?.RequestURI ?? ''
|
|
276
|
+
this.RemoteAddr = init?.RemoteAddr ?? ''
|
|
277
|
+
this.ctx = (init as { ctx?: context.Context } | undefined)?.ctx ?? context.Background()
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
public Context(): context.Context {
|
|
281
|
+
return this.ctx
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
public WithContext(ctx: context.Context): Request {
|
|
285
|
+
return this.Clone(ctx)
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
public Clone(ctx: context.Context): Request {
|
|
289
|
+
return new Request({
|
|
290
|
+
Method: this.Method,
|
|
291
|
+
URL: this.URL?.clone != null ? this.URL.clone() : this.URL == null ? null : { ...this.URL },
|
|
292
|
+
Body: this.Body,
|
|
293
|
+
Header: this.Header,
|
|
294
|
+
ContentLength: this.ContentLength,
|
|
295
|
+
RequestURI: this.RequestURI,
|
|
296
|
+
RemoteAddr: this.RemoteAddr,
|
|
297
|
+
ctx,
|
|
298
|
+
})
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
public UserAgent(): string {
|
|
302
|
+
return Header_Get(this.Header, 'User-Agent')
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
public FormValue(key: string): string {
|
|
306
|
+
const query = this.URL?.Query
|
|
307
|
+
return typeof query === 'function' ? query.call(this.URL).Get(key) : ''
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
|
|
59
311
|
export class Response {
|
|
312
|
+
public Status: string
|
|
60
313
|
public StatusCode: number
|
|
61
314
|
public Body: io.ReadCloser | null
|
|
62
315
|
public Header: Header
|
|
63
316
|
|
|
64
317
|
constructor(init?: Partial<Response>) {
|
|
318
|
+
this.Status = init?.Status ?? ''
|
|
65
319
|
this.StatusCode = init?.StatusCode ?? 0
|
|
66
320
|
this.Body = init?.Body ?? null
|
|
67
321
|
this.Header = init?.Header ?? new Header()
|
|
322
|
+
if (this.Status === '' && this.StatusCode !== 0) {
|
|
323
|
+
const text = StatusText(this.StatusCode)
|
|
324
|
+
this.Status = text === '' ? String(this.StatusCode) : `${this.StatusCode} ${text}`
|
|
325
|
+
}
|
|
68
326
|
}
|
|
69
327
|
|
|
70
328
|
public clone(): Response {
|
|
71
329
|
return new Response({
|
|
72
330
|
Body: this.Body,
|
|
73
331
|
Header: this.Header,
|
|
332
|
+
Status: this.Status,
|
|
74
333
|
StatusCode: this.StatusCode,
|
|
75
334
|
})
|
|
76
335
|
}
|
|
77
336
|
}
|
|
78
337
|
|
|
338
|
+
export class Client {
|
|
339
|
+
public Transport: RoundTripper | null
|
|
340
|
+
|
|
341
|
+
constructor(init?: Partial<Client>) {
|
|
342
|
+
this.Transport = init?.Transport ?? null
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
public async Do(
|
|
346
|
+
_req: Request | $.VarRef<Request> | null,
|
|
347
|
+
): Promise<[Response | null, $.GoError]> {
|
|
348
|
+
return await (this.Transport ?? DefaultTransport).RoundTrip(_req)
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
export const DefaultClient = new Client()
|
|
353
|
+
|
|
354
|
+
export interface RoundTripper {
|
|
355
|
+
RoundTrip(req: Request | $.VarRef<Request> | null): [Response | null, $.GoError] | Promise<[Response | null, $.GoError]>
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
class defaultTransport implements RoundTripper {
|
|
359
|
+
public async RoundTrip(req: Request | $.VarRef<Request> | null): Promise<[Response | null, $.GoError]> {
|
|
360
|
+
const request = $.pointerValue<Request | null>(req)
|
|
361
|
+
if (request == null) {
|
|
362
|
+
return [null, errors.New('net/http: nil Request')]
|
|
363
|
+
}
|
|
364
|
+
const host = request.URL?.Host ?? ''
|
|
365
|
+
const handler = host === '' ? null : inProcessServers.get(host)
|
|
366
|
+
if (handler == null) {
|
|
367
|
+
return [null, errors.New('net/http: Client.Do is not implemented in GoScript')]
|
|
368
|
+
}
|
|
369
|
+
const recorder = new memoryResponseWriter()
|
|
370
|
+
const served = handler.ServeHTTP(recorder, request)
|
|
371
|
+
if (served instanceof Promise) {
|
|
372
|
+
await served
|
|
373
|
+
}
|
|
374
|
+
return [recorder.Result(), null]
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
export const DefaultTransport: RoundTripper = new defaultTransport()
|
|
379
|
+
|
|
380
|
+
export interface FileSystem {
|
|
381
|
+
Open(name: string): [File | null, $.GoError]
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
export interface File extends io.Closer, io.Reader, io.Seeker {
|
|
385
|
+
Readdir(count: number): [$.Slice<fs.FileInfo>, $.GoError]
|
|
386
|
+
Stat(): [fs.FileInfo, $.GoError]
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
export interface Handler {
|
|
390
|
+
ServeHTTP(w: ResponseWriter | null, r: Request | $.VarRef<Request> | null): void | Promise<void>
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
export type HandlerFunc = (
|
|
394
|
+
w: ResponseWriter | null,
|
|
395
|
+
r: Request | $.VarRef<Request> | null,
|
|
396
|
+
) => void | Promise<void>
|
|
397
|
+
|
|
398
|
+
export function HandlerFunc_ServeHTTP(
|
|
399
|
+
h: HandlerFunc,
|
|
400
|
+
w: ResponseWriter | null,
|
|
401
|
+
r: Request | $.VarRef<Request> | null,
|
|
402
|
+
): void | Promise<void> {
|
|
403
|
+
return h(w, r)
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
export class Server {
|
|
407
|
+
public Addr: string
|
|
408
|
+
public BaseContext: ((listener: any) => context.Context) | null
|
|
409
|
+
public Handler: Handler | null
|
|
410
|
+
public ReadHeaderTimeout: number
|
|
411
|
+
public WriteTimeout: number
|
|
412
|
+
|
|
413
|
+
constructor(init?: Partial<Server>) {
|
|
414
|
+
this.Addr = init?.Addr ?? ''
|
|
415
|
+
this.BaseContext = init?.BaseContext ?? null
|
|
416
|
+
this.Handler = init?.Handler ?? null
|
|
417
|
+
this.ReadHeaderTimeout = init?.ReadHeaderTimeout ?? 0
|
|
418
|
+
this.WriteTimeout = init?.WriteTimeout ?? 0
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
public ListenAndServe(): $.GoError {
|
|
422
|
+
return errors.New('net/http: Server.ListenAndServe is not implemented in GoScript')
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
public ListenAndServeTLS(_certFile: string, _keyFile: string): $.GoError {
|
|
426
|
+
return errors.New('net/http: Server.ListenAndServeTLS is not implemented in GoScript')
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
public Close(): $.GoError {
|
|
430
|
+
return null
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
public Shutdown(_ctx: context.Context): $.GoError {
|
|
434
|
+
return null
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
export class PushOptions {
|
|
439
|
+
public Header: Header
|
|
440
|
+
|
|
441
|
+
constructor(init?: Partial<PushOptions>) {
|
|
442
|
+
this.Header = init?.Header ?? new Header()
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
export interface Flusher {
|
|
447
|
+
Flush(): void
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
export interface Hijacker {
|
|
451
|
+
Hijack(): [any, any, $.GoError]
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
export interface Pusher {
|
|
455
|
+
Push(target: string, opts: PushOptions | $.VarRef<PushOptions> | null): $.GoError
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
export class ResponseController {
|
|
459
|
+
public rw: ResponseWriter | null
|
|
460
|
+
|
|
461
|
+
constructor(rw: ResponseWriter | null) {
|
|
462
|
+
this.rw = rw
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
public Flush(): $.GoError {
|
|
466
|
+
const flusher = this.rw as (Flusher & ResponseWriter) | null
|
|
467
|
+
flusher?.Flush?.()
|
|
468
|
+
return null
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
export function NewResponseController(rw: ResponseWriter | null): ResponseController {
|
|
473
|
+
return new ResponseController(rw)
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
export class ServeMux implements Handler {
|
|
477
|
+
private handlers = new Map<string, Handler>()
|
|
478
|
+
|
|
479
|
+
public Handle(pattern: string, handler: Handler | null): void {
|
|
480
|
+
if (handler != null) {
|
|
481
|
+
this.handlers.set(pattern, handler)
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
public HandleFunc(pattern: string, handler: HandlerFunc): void {
|
|
486
|
+
this.Handle(pattern, { ServeHTTP: handler })
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
public Handler(r: Request | $.VarRef<Request> | null): [Handler | null, string] {
|
|
490
|
+
const req = $.pointerValue<Request | null>(r)
|
|
491
|
+
const path = req?.URL?.Path ?? ''
|
|
492
|
+
const handler = this.handlers.get(path) ?? null
|
|
493
|
+
return [handler, handler == null ? '' : path]
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
public ServeHTTP(w: ResponseWriter | null, r: Request | $.VarRef<Request> | null): void | Promise<void> {
|
|
497
|
+
const [handler] = this.Handler(r)
|
|
498
|
+
if (handler == null) {
|
|
499
|
+
NotFound(w, r)
|
|
500
|
+
return
|
|
501
|
+
}
|
|
502
|
+
return handler.ServeHTTP(w, r)
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
const defaultServeMux = new ServeMux()
|
|
507
|
+
|
|
508
|
+
export function NewServeMux(): ServeMux {
|
|
509
|
+
return new ServeMux()
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
export function HandleFunc(pattern: string, handler: HandlerFunc): void {
|
|
513
|
+
defaultServeMux.HandleFunc(pattern, handler)
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
export function StripPrefix(prefix: string, handler: Handler | null): Handler {
|
|
517
|
+
return {
|
|
518
|
+
ServeHTTP(w, r) {
|
|
519
|
+
const req = $.pointerValue<Request | null>(r)
|
|
520
|
+
if (req?.URL != null && typeof req.URL.Path === 'string' && req.URL.Path.startsWith(prefix)) {
|
|
521
|
+
req.URL = { ...req.URL, Path: req.URL.Path.slice(prefix.length) || '/' }
|
|
522
|
+
}
|
|
523
|
+
return handler?.ServeHTTP(w, req)
|
|
524
|
+
},
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
export function Error(w: ResponseWriter | null, error: string, code: number): void {
|
|
529
|
+
w?.WriteHeader(code)
|
|
530
|
+
w?.Write($.stringToBytes(error + '\n'))
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
export function NotFound(w: ResponseWriter | null, _r: Request | $.VarRef<Request> | null): void {
|
|
534
|
+
Error(w, '404 page not found', StatusNotFound)
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
export function Redirect(
|
|
538
|
+
w: ResponseWriter | null,
|
|
539
|
+
_r: Request | $.VarRef<Request> | null,
|
|
540
|
+
url: string,
|
|
541
|
+
code: number,
|
|
542
|
+
): void {
|
|
543
|
+
const header = w?.Header()
|
|
544
|
+
if (header != null) {
|
|
545
|
+
Header_Set(header, 'Location', url)
|
|
546
|
+
}
|
|
547
|
+
w?.WriteHeader(code)
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
export function ParseTime(text: string): [time.Time, $.GoError] {
|
|
551
|
+
const date = new globalThis.Date(text)
|
|
552
|
+
if (isNaN(date.getTime())) {
|
|
553
|
+
return [new time.Time(), $.newError(`parsing time "${text}" as HTTP-date: cannot parse`)]
|
|
554
|
+
}
|
|
555
|
+
return [time.UnixMilli(date.getTime()), null]
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
export function NewRequest(
|
|
559
|
+
method: string,
|
|
560
|
+
url: string,
|
|
561
|
+
body: io.Reader | null,
|
|
562
|
+
): [Request | null, $.GoError] {
|
|
563
|
+
return NewRequestWithContext(null, method, url, body)
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
export function NewRequestWithContext(
|
|
567
|
+
_ctx: context.Context,
|
|
568
|
+
method: string,
|
|
569
|
+
url: string,
|
|
570
|
+
body: io.Reader | null,
|
|
571
|
+
): [Request | null, $.GoError] {
|
|
572
|
+
if (method === '') {
|
|
573
|
+
method = MethodGet
|
|
574
|
+
}
|
|
575
|
+
const parsedURL = parseRequestURL(url)
|
|
576
|
+
return [new Request({ Method: method, URL: parsedURL, Body: body, RequestURI: parsedURL.Path, ctx: _ctx }), null]
|
|
577
|
+
}
|
|
578
|
+
|
|
79
579
|
export function Get(_url: string): [Response | null, $.GoError] {
|
|
80
580
|
return [null, errors.New('net/http: Get is not implemented in GoScript')]
|
|
81
581
|
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest'
|
|
2
|
+
|
|
3
|
+
import { Header, Header_Get, ResponseWriter } from '../index.js'
|
|
4
|
+
import { Handler, Index } from './index.js'
|
|
5
|
+
|
|
6
|
+
class writer implements ResponseWriter {
|
|
7
|
+
public status = 200
|
|
8
|
+
public header = new Header()
|
|
9
|
+
public chunks: number[] = []
|
|
10
|
+
|
|
11
|
+
Header(): Header {
|
|
12
|
+
return this.header
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
Write(p: number[] | null): [number, null] {
|
|
16
|
+
this.chunks.push(...(p ?? []))
|
|
17
|
+
return [p?.length ?? 0, null]
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
WriteHeader(statusCode: number): void {
|
|
21
|
+
this.status = statusCode
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
String(): string {
|
|
25
|
+
return Buffer.from(this.chunks).toString('utf8')
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
describe('net/http/pprof override', () => {
|
|
30
|
+
it('serves the index text expected by debug handlers', () => {
|
|
31
|
+
const w = new writer()
|
|
32
|
+
|
|
33
|
+
Index(w, null)
|
|
34
|
+
|
|
35
|
+
expect(Header_Get(w.Header(), 'Content-Type')).toContain('text/html')
|
|
36
|
+
expect(w.String()).toContain('full goroutine stack dump')
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
it('serves named runtime profiles', () => {
|
|
40
|
+
const w = new writer()
|
|
41
|
+
|
|
42
|
+
Handler('goroutine').ServeHTTP(w, null)
|
|
43
|
+
|
|
44
|
+
expect(Header_Get(w.Header(), 'Content-Type')).toContain('text/plain')
|
|
45
|
+
expect(w.String()).toContain('goroutine profile')
|
|
46
|
+
})
|
|
47
|
+
})
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import * as $ from '@goscript/builtin/index.js'
|
|
2
|
+
import * as http from '@goscript/net/http/index.js'
|
|
3
|
+
import * as pprof from '@goscript/runtime/pprof/index.js'
|
|
4
|
+
|
|
5
|
+
function writeString(w: http.ResponseWriter | null, value: string): void {
|
|
6
|
+
w?.Write($.stringToBytes(value))
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function Index(w: http.ResponseWriter | null, _r: http.Request | $.VarRef<http.Request> | null): void {
|
|
10
|
+
const header = w?.Header()
|
|
11
|
+
if (header != null) {
|
|
12
|
+
http.Header_Set(header, 'Content-Type', 'text/html; charset=utf-8')
|
|
13
|
+
}
|
|
14
|
+
writeString(w, '<html><body><a href="goroutine?debug=2">full goroutine stack dump</a></body></html>')
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function Cmdline(w: http.ResponseWriter | null, _r: http.Request | $.VarRef<http.Request> | null): void {
|
|
18
|
+
const header = w?.Header()
|
|
19
|
+
if (header != null) {
|
|
20
|
+
http.Header_Set(header, 'Content-Type', 'text/plain; charset=utf-8')
|
|
21
|
+
}
|
|
22
|
+
writeString(w, 'goscript')
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function Profile(w: http.ResponseWriter | null, _r: http.Request | $.VarRef<http.Request> | null): void {
|
|
26
|
+
const header = w?.Header()
|
|
27
|
+
if (header != null) {
|
|
28
|
+
http.Header_Set(header, 'Content-Type', 'application/octet-stream')
|
|
29
|
+
}
|
|
30
|
+
writeString(w, 'cpu profile\n')
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function Symbol(w: http.ResponseWriter | null, _r: http.Request | $.VarRef<http.Request> | null): void {
|
|
34
|
+
const header = w?.Header()
|
|
35
|
+
if (header != null) {
|
|
36
|
+
http.Header_Set(header, 'Content-Type', 'text/plain; charset=utf-8')
|
|
37
|
+
}
|
|
38
|
+
writeString(w, 'num_symbols: 0\n')
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function Trace(w: http.ResponseWriter | null, _r: http.Request | $.VarRef<http.Request> | null): void {
|
|
42
|
+
const header = w?.Header()
|
|
43
|
+
if (header != null) {
|
|
44
|
+
http.Header_Set(header, 'Content-Type', 'application/octet-stream')
|
|
45
|
+
}
|
|
46
|
+
writeString(w, 'trace\n')
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export function Handler(name: string): http.Handler {
|
|
50
|
+
return {
|
|
51
|
+
ServeHTTP(w) {
|
|
52
|
+
const header = w?.Header()
|
|
53
|
+
if (header != null) {
|
|
54
|
+
http.Header_Set(header, 'Content-Type', 'text/plain; charset=utf-8')
|
|
55
|
+
}
|
|
56
|
+
const profile = pprof.Lookup(name)
|
|
57
|
+
if (profile == null) {
|
|
58
|
+
http.NotFound(w, null)
|
|
59
|
+
return
|
|
60
|
+
}
|
|
61
|
+
writeString(w, `${name} profile\n`)
|
|
62
|
+
profile.WriteTo(w, 1)
|
|
63
|
+
},
|
|
64
|
+
}
|
|
65
|
+
}
|