Starting a simple web server using HTTP.jl

I am working through Adrian Salceanu’s book “Julia Programming Projects” and am having difficulties because the versions of modules he specifies in the book are not necessarily compatible as far as my package manager is concerned, so I have to resort to using the latest versions in most cases, and the rapid development means there are many breaking changes or documentation is missing.

I am trying to start a very simple “Hello World” web server using HTTP.jl. The version recommended in the book is 0.7. I can find documentation for 0.6 and 0.8 neither of which seem to match the code example in the book which is as follows:

using HTTP, Sockets

const HOST = ip"0.0.0.0"
const PORT = 9999

router = HTTP.Router()
server = HTTP.Server(router)

HTTP.register!(router, “/”, HTTP.HandlerFunction(req → HTTP.Messages.Response(200, “Hello World”)))
HTTP.register!(router, “/bye”, HTTP.HandlerFunction(req → HTTP.Messages.Response(200, “Bye”)))
HTTP.register!(router, “*”, HTTP.HandlerFunction(req → HTTP.Messages.Response(404, “Not found”)))

HTTP.serve(server, HOST, PORT)

I get an error that HTTP.Server is not recognised (and neither would I expect it to be looking at both 0.6 and 0.8 documentation). But also, by the same token, neither should HTTP.Router() or HTTP.HandlerFunction. So, I tried substituting this line (based on the documentation):

server = Sockets.listen(HOST, PORT)

The server appears to start or possibly hang. There is no logging as the book suggests there ought to be and I can’t connect via a browser. When I do Ctrl+C in Juno I get an interrupt message that tells me the server was listening on the default localhost and port (8081) and not what I specified. However, I can’t connect via the default credentials either. No error is reported.

I am confused between what I see in the documentation and the book, which don’t seem to bare much relation to each other. I am also confused as to why in both the book and the documentation it seems you can reference modules at a higher level than where they really exist (e.g. The docs say that Router is of type HTTP.Handlers.Router but referenced as HTTP.Router. This seems to work with Router but not with Server - this is very confusing).

I am on Julia 1.4 and HTTP 0.8.13. Genie.JL looks familiar from my use of Express.js but before I go down that sort of route I want to understand this most basic of use-cases using the un-wrapped HTTP module. I’d appreciate it if anybody could help this novice.

Check the information about HTTP.Handers or the web doc of the package, that it has a lot of examples.

I put you an simple example that is working in my computer:

const ROUTER = HTTP.Router()
HTTP.@register(ROUTER, "GET", "/*", req->HTTP.Response(200, "Hi"))
# You can register more
HTTP.@register(ROUTER, "GET", "/bye", req->HTTP.Response(200, "Bye!"))
HTTP.serve(ROUTER, Sockets.localhost, 8081)

I hope it could help you.

4 Likes

This works for me too and is very close to the book. Thanks!

I still don’t understand why I can call HTTP.Router, when the documentation clear states it should be HTTP.Handler.Router or is the the difference between a Type in Julia and inheritance in OOP?