http: turns out we do need to handle port number in host header, and client needs to send it but only for non-default ports, since sending it for the default port breaks Twitter's HTTP server (reported by John Benediktsson)
parent
6e0cb74b13
commit
97e6ac1c50
|
@ -1,13 +1,14 @@
|
||||||
! Copyright (C) 2005, 2010 Slava Pestov.
|
! Copyright (C) 2005, 2010 Slava Pestov.
|
||||||
! See http://factorcode.org/license.txt for BSD license.
|
! See http://factorcode.org/license.txt for BSD license.
|
||||||
USING: assocs kernel math math.parser namespaces make
|
USING: assocs combinators.short-circuit kernel math math.parser
|
||||||
sequences strings splitting calendar continuations accessors vectors
|
namespaces make sequences strings splitting calendar
|
||||||
math.order hashtables byte-arrays destructors
|
continuations accessors vectors math.order hashtables
|
||||||
io io.sockets io.streams.string io.files io.timeouts
|
byte-arrays destructors io io.sockets io.streams.string io.files
|
||||||
io.pathnames io.encodings io.encodings.string io.encodings.ascii
|
io.timeouts io.pathnames io.encodings io.encodings.string
|
||||||
io.encodings.utf8 io.encodings.binary io.encodings.iana io.crlf
|
io.encodings.ascii io.encodings.utf8 io.encodings.binary
|
||||||
io.streams.duplex fry ascii urls urls.encoding present locals
|
io.encodings.iana io.crlf io.streams.duplex fry ascii urls
|
||||||
http http.parsers http.client.post-data mime.types ;
|
urls.encoding present locals http http.parsers
|
||||||
|
http.client.post-data mime.types ;
|
||||||
IN: http.client
|
IN: http.client
|
||||||
|
|
||||||
ERROR: too-many-redirects ;
|
ERROR: too-many-redirects ;
|
||||||
|
@ -21,8 +22,19 @@ ERROR: too-many-redirects ;
|
||||||
[ "HTTP/" write version>> write crlf ]
|
[ "HTTP/" write version>> write crlf ]
|
||||||
tri ;
|
tri ;
|
||||||
|
|
||||||
|
: default-port? ( url -- ? )
|
||||||
|
{
|
||||||
|
[ port>> not ]
|
||||||
|
[ [ port>> ] [ protocol>> protocol-port ] bi = ]
|
||||||
|
} 1|| ;
|
||||||
|
|
||||||
|
: unparse-host ( url -- string )
|
||||||
|
dup default-port? [ host>> ] [
|
||||||
|
[ host>> ] [ port>> number>string ] bi ":" glue
|
||||||
|
] if ;
|
||||||
|
|
||||||
: set-host-header ( request header -- request header )
|
: set-host-header ( request header -- request header )
|
||||||
over url>> host>> "host" pick set-at ;
|
over url>> unparse-host "host" pick set-at ;
|
||||||
|
|
||||||
: set-cookie-header ( header cookies -- header )
|
: set-cookie-header ( header cookies -- header )
|
||||||
unparse-cookie "cookie" pick set-at ;
|
unparse-cookie "cookie" pick set-at ;
|
||||||
|
|
|
@ -14,6 +14,15 @@ IN: http.tests
|
||||||
|
|
||||||
[ "application/octet-stream" f ] [ "application/octet-stream" parse-content-type ] unit-test
|
[ "application/octet-stream" f ] [ "application/octet-stream" parse-content-type ] unit-test
|
||||||
|
|
||||||
|
[ "localhost" f ] [ "localhost" parse-host ] unit-test
|
||||||
|
[ "localhost" 8888 ] [ "localhost:8888" parse-host ] unit-test
|
||||||
|
|
||||||
|
[ "localhost" ] [ T{ url { protocol "http" } { host "localhost" } } unparse-host ] unit-test
|
||||||
|
[ "localhost" ] [ T{ url { protocol "http" } { host "localhost" } { port 80 } } unparse-host ] unit-test
|
||||||
|
[ "localhost" ] [ T{ url { protocol "https" } { host "localhost" } { port 443 } } unparse-host ] unit-test
|
||||||
|
[ "localhost:8080" ] [ T{ url { protocol "http" } { host "localhost" } { port 8080 } } unparse-host ] unit-test
|
||||||
|
[ "localhost:8443" ] [ T{ url { protocol "https" } { host "localhost" } { port 8443 } } unparse-host ] unit-test
|
||||||
|
|
||||||
: lf>crlf ( string -- string' ) "\n" split "\r\n" join ;
|
: lf>crlf ( string -- string' ) "\n" split "\r\n" join ;
|
||||||
|
|
||||||
STRING: read-request-test-1
|
STRING: read-request-test-1
|
||||||
|
@ -80,15 +89,32 @@ Host: www.sex.com
|
||||||
] with-string-reader
|
] with-string-reader
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
|
STRING: read-request-test-2'
|
||||||
|
HEAD /bar HTTP/1.1
|
||||||
|
Host: www.sex.com:101
|
||||||
|
|
||||||
|
;
|
||||||
|
|
||||||
|
[
|
||||||
|
T{ request
|
||||||
|
{ url T{ url { host "www.sex.com" } { port 101 } { path "/bar" } } }
|
||||||
|
{ method "HEAD" }
|
||||||
|
{ version "1.1" }
|
||||||
|
{ header H{ { "host" "www.sex.com:101" } } }
|
||||||
|
{ cookies V{ } }
|
||||||
|
{ redirects 10 }
|
||||||
|
}
|
||||||
|
] [
|
||||||
|
read-request-test-2' lf>crlf [
|
||||||
|
read-request
|
||||||
|
] with-string-reader
|
||||||
|
] unit-test
|
||||||
|
|
||||||
STRING: read-request-test-3
|
STRING: read-request-test-3
|
||||||
GET nested HTTP/1.0
|
GET nested HTTP/1.0
|
||||||
|
|
||||||
;
|
;
|
||||||
|
|
||||||
[ read-request-test-3 lf>crlf [ read-request ] with-string-reader ]
|
|
||||||
[ "Bad request: URL" = ]
|
|
||||||
must-fail-with
|
|
||||||
|
|
||||||
STRING: read-request-test-4
|
STRING: read-request-test-4
|
||||||
GET /blah HTTP/1.0
|
GET /blah HTTP/1.0
|
||||||
Host: "www.amazon.com"
|
Host: "www.amazon.com"
|
||||||
|
|
|
@ -75,8 +75,9 @@ SYMBOL: upload-limit
|
||||||
] when ;
|
] when ;
|
||||||
|
|
||||||
: extract-host ( request -- request )
|
: extract-host ( request -- request )
|
||||||
[ ] [ url>> ] [ "host" header dup [ url-decode ] when ] tri
|
[ ] [ url>> ] [ "host" header parse-host ] tri
|
||||||
>>host drop ;
|
[ >>host ] [ >>port ] bi*
|
||||||
|
drop ;
|
||||||
|
|
||||||
: extract-cookies ( request -- request )
|
: extract-cookies ( request -- request )
|
||||||
dup "cookie" header [ parse-cookie >>cookies ] when* ;
|
dup "cookie" header [ parse-cookie >>cookies ] when* ;
|
||||||
|
|
Loading…
Reference in New Issue