wss:// adds the websocket upgrade headers to the request and then gets replaced by https://
USING: accessors arrays ascii assocs calendar combinators
combinators.short-circuit continuations destructors effects
environment hashtables http http.client.post-data http.parsers
-io io.crlf io.encodings io.encodings.ascii io.encodings.binary
-io.encodings.iana io.encodings.string io.files io.pathnames
-io.sockets io.sockets.secure io.timeouts kernel math math.order
-math.parser mime.types namespaces present sequences splitting
-urls vocabs.loader ;
+http.websockets io io.crlf io.encodings io.encodings.ascii
+io.encodings.binary io.encodings.iana io.encodings.string
+io.files io.pathnames io.sockets io.sockets.secure io.timeouts
+kernel math math.order math.parser mime.types namespaces present
+protocols sequences splitting urls vocabs.loader ;
IN: http.client
ERROR: too-many-redirects ;
: default-port? ( url -- ? )
{
[ port>> not ]
- [ [ port>> ] [ protocol>> protocol-port ] bi = ]
+ [ [ port>> ] [ protocol>> lookup-protocol-port ] bi = ]
} 1|| ;
: unparse-host ( url -- string )
] with-destructors
] with-variable ; inline recursive
+: add-default-headers ( request -- request )
+ dup url>> protocol>> {
+ ! { [ dup { "http" "https" } member? ] [ drop add-connection-close-header ] }
+ { [ dup { "ws" "wss" } member? ] [ drop add-websocket-upgrade-headers ] }
+ [ drop ]
+ } cond ;
+
: <client-request> ( url method -- request )
<request>
swap >>method
- swap request-url >>url ; inline
+ swap request-url >>url
+ add-default-headers ; inline
: with-http-request ( request quot: ( chunk -- ) -- response/stream )
do-http-request check-response ; inline
"Factor http.client" "User-Agent" set-header
max-redirects >>redirects ;
+: add-connection-close-header ( request -- request )
+ "close" "Connection" set-header ;
+
: header ( request/response key -- value )
swap header>> at ;
io io.crlf io.encodings io.encodings.ascii io.encodings.iana
io.encodings.utf8 io.servers io.sockets io.sockets.secure
io.streams.limited kernel logging logging.insomniac math
-mime.types namespaces present sequences splitting tools.time
-urls vectors vocabs vocabs.refresh xml.writer ;
+mime.types namespaces present protocols sequences splitting
+tools.time urls vectors vocabs vocabs.refresh xml.writer ;
IN: http.server
GENERIC: write-response ( response -- )
: <http-server> ( -- server )
ascii http-server new-threaded-server
"http.server" >>name
- "http" protocol-port >>insecure
- "https" protocol-port >>secure ;
+ "http" lookup-protocol-port >>insecure
+ "https" lookup-protocol-port >>secure ;
: httpd ( port -- http-server )
<http-server>
"no-cache" "Pragma" set-header
"no-cache" "Cache-Control" set-header
"permessage-deflate; client_max_window_bits" "Sec-WebSocket-Extensions" set-header
- dup url>> host>> "Host" set-header ;
+ dup url>> host>> "Host" set-header
+ dup url>> [ "ws" = "http" "https" ? ] change-protocol drop ;
CONSTANT: websocket-opcode-continue-frame 0
CONSTANT: websocket-opcode-text-frame 1
{ } [ f 0 <inet4> <datagram> dispose ] unit-test
{ } [ f 0 <inet6> <datagram> dispose ] unit-test
-{ 80 } [ "http" protocol-port ] unit-test
-{ f } [ f protocol-port ] unit-test
+{ 80 } [ "http" lookup-protocol-port ] unit-test
+{ f } [ f lookup-protocol-port ] unit-test
{ "http" } [ 80 port-protocol ] unit-test
{ f } [ f port-protocol ] unit-test
USING: accessors ascii assocs combinators
combinators.short-circuit io.pathnames io.sockets
io.sockets.secure kernel lexer linked-assocs make math.parser
-multiline namespaces peg.ebnf present sequences
+multiline namespaces peg.ebnf present protocols sequences
sequences.generalizations splitting strings strings.parser
urls.encoding vocabs.loader ;
] [ 2drop ] if ;
: url-port ( url -- port/f )
- [ port>> ] [ protocol>> protocol-port ] bi over =
+ [ port>> ] [ protocol>> lookup-protocol-port ] bi over =
[ drop f ] when ;
: ipv6-host ( host -- host/ipv6 ipv6? )
[
[ host>> ipv6-host drop ]
[ port>> ]
- [ protocol>> protocol-port ]
+ [ protocol>> lookup-protocol-port ]
tri or <inet>
] [
dup protocol>> secure-protocol?
[ port>> >>port ] bi ;
: ensure-port ( url -- url' )
- clone dup protocol>> '[ _ protocol-port or ] change-port ;
+ clone dup protocol>> '[ _ lookup-protocol-port or ] change-port ;
! Literal syntax
SYNTAX: URL" lexer get skip-blank parse-string >url suffix! ;
IN: discord
CONSTANT: discord-api-url "https://discord.com/api/v10"
-CONSTANT: discord-bot-gateway "https://gateway.discord.gg/gateway/bot?v=10&encoding=json"
+CONSTANT: discord-bot-gateway "wss://gateway.discord.gg/gateway/bot?v=10&encoding=json"
TUPLE: discord-webhook url id token ;
: discord-connect ( config -- discord-bot )
\ discord-bot-config [
discord-bot-gateway <get-request>
- add-websocket-upgrade-headers
add-discord-auth-header
[ drop ] do-http-request
- [ in>> stream>> ] [ out>> stream>> ] bi
- \ discord-bot-config get <discord-bot>
- dup '[
- _ \ discord-bot [
- discord-bot get [ in>> ] [ out>> ] bi
- [
- [ handle-discord-websocket ] read-websocket-loop
- ] with-streams
- ] with-variable
- ] "Discord Bot" spawn
- >>bot-thread
+ dup response? [
+ throw
+ ] [
+ [ in>> stream>> ] [ out>> stream>> ] bi
+ \ discord-bot-config get <discord-bot>
+ dup '[
+ _ \ discord-bot [
+ discord-bot get [ in>> ] [ out>> ] bi
+ [
+ [ handle-discord-websocket ] read-websocket-loop
+ ] with-streams
+ ] with-variable
+ ] "Discord Bot" spawn
+ >>bot-thread
+ ] if
] with-variable ;
: <http2-server> ( -- server )
ascii http2-server new-threaded-server
"http2.server" >>name
- "http" protocol-port >>insecure
- "https" protocol-port >>secure ;
+ "http" lookup-protocol-port >>insecure
+ "https" lookup-protocol-port >>secure ;