HTTP
std/http fetches web pages and talks to web APIs. http.Fetch( url ) sends
a GET and returns the whole reply as a Response: the status, the headers
and the body. https URLs work the same way, encrypted by std/tls.
#cmdline "-mt"
#import "std/http"
#import "std/net"
#import "std/fs"
'' A web server that answers one request, on this machine, so the example
'' needs no network. It reads the request up to the blank line, then replies.
sub Serve( byval p as any ptr )
dim as net.TcpListener ptr lis = p
dim c as net.TcpStream
if lis->Accept( c, 5000 ).IsOk( ) = false then exit sub
dim as string seen
dim as ubyte b( 0 to 1023 )
while instr( seen, !"\r\n\r\n" ) = 0
dim got as fs.FsResultI64 = c.Read( @b( 0 ), 1024 )
if got.IsOk( ) = false orelse got.Value( ) = 0 then exit while
for i as long = 0 to got.Value( ) - 1
seen &= chr( b( i ) )
next
wend
c.WriteUtf8( !"HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\n" & _
!"Content-Length: 13\r\n\r\nhello, client" )
c.Close( )
end sub
sub Main( )
dim lis as net.TcpListener
lis.Bind( net.SocketAddress( net.Loopback( ), 0 ) )
dim as long port = lis.LocalAddress( ).Value( ).Port
dim th as any ptr = threadcreate( @Serve, @lis, 1024 * 1024 )
dim r as http.HttpResultResponse = http.Fetch( "http://127.0.0.1:" & port & "/greeting" )
if r.IsOk( ) then
print r.Value( ).StatusCode; " "; r.Value( ).Reason
print r.Value( ).Header.Get( "content-type" ).ValueOr( "?" )
print r.Value( ).Text( )
end if
threadwait( th )
dim bad as http.HttpResultResponse = http.Fetch( "ftp://example.com/file" )
print bad.Failure( ).Message( )
end sub
Main( )
Output
200 OK
text/plain
hello, client
Send 'ftp://example.com/file': unsupported URL scheme
The example runs its own tiny server on this machine so that it needs no
network: Serve accepts one connection on a second thread, reads the request
and writes a reply by hand. That is the whole of HTTP/1.1 on the wire — a
status line, headers, a blank line, then the body.
On the client side Header.Get finds a header whatever its case, and returns
an Optional, because a header may be missing. Text( ) decodes the body as
UTF-8. A status such as 404 is not an error: the request worked and the
server answered, so check StatusCode. An error is a request that could not be
made at all, like the ftp: URL, which std/http does not speak.
For more than one request make an http.Client: it keeps connections open and
reuses them, follows redirects, and holds settings such as TimeoutMs.
Client.Open hands the body over as a stream instead of reading it all, for
downloads too large to keep in memory.
Activities
- Change the server's status line to
HTTP/1.1 404 Not Foundand printr.Value( ).IsSuccess( ). - Fetch
"http://127.0.0.1:1/", where nothing listens, and print the failure'sMessage( ).