Video course contents16
All video lessons

LESSON 16 · HHY 1.7.0

Build Your First JSON API

Serve a local /hello route and read a query parameter using the built-in Web Runtime.

4:42 · English audio & captions

Your progress stays in this browser. No account needed.

Read the companion manual chapter

Chapters & transcript

Select a timestamp to jump in the video. Expand a title to read the transcript and code.

From client to server

Until now, our scripts have consumed data or produced files. In this lesson, an HHY program will answer an HTTP request. We will create one local route called hello, read a name from the query string, and return a JSON object. The response you see is produced by the built in Web Runtime. This is the final project in the first course section, and it connects our knowledge of functions and data values to a running network service.

hhy
GET /hello?name=Ada
200 OK
{"ok": true, "name": "Ada"}

Actual response from the local HHY server.

Use the built in Web module

Create app dot HHY and import web. This gives us the core application and response builders described in the Web Runtime chapter. We are using those directly, so this example does not require installing a separate web framework. The whole application is small enough to read at once, but it still has three distinct responsibilities: a handler that computes a response, a route that selects the handler, and a listener that accepts connections.

hhy
import web

This example uses the core Runtime, without an extra framework.

Write a response function

Define a function named hello with one request parameter. The request exposes parsed query parameters, so we read name and put it in a small response object. Web JSON creates the HTTP response representation from ordinary data. Notice the difference from printing JSON in a command line script: a printed line goes to the server's terminal, while a returned Web response goes to the client that made the request. The handler's job is to return that response.

hhy
fn hello(request) {
    return web.json({ ok: true, name: request.query_params.name })
}

The handler receives a Web request.

Connect the route

Create an application and register a GET route at slash hello. The route path determines which incoming requests should reach our function. The function name is passed as a value, so the registration step does not call the handler with a made up request. The runtime invokes it later for a matching request. Keep the leading slash in the route and use the same path in your test command; an incorrect URL should not be mistaken for a failure to start the server.

hhy
web.app()
    |> web.get("/hello", hello)

Route path and handler are separate values.

Bind a local listener

Add the listener with an explicit host, port, and worker count. Loopback keeps this tutorial server on your own computer. Port ninety three sixteen is separate from the documentation website, so the two applications can run at the same time. One worker is sufficient for this example. The application is now a persistent service: after starting it, the terminal remains occupied while it waits for requests. That waiting state is expected, rather than a script that forgot to finish.

hhy
    |> web.listen({ host: "127.0.0.1", port: 9316, workers: 1 })

Loopback only; leave port 9200 for the documentation website.

Start and request

Run HHY serve with the application file, then open another terminal and request the local URL with curl. Quote the URL so your shell does not interpret the question mark as a filename pattern. Inspect the returned JSON and confirm that name is Ada. You have now exercised the full path: the listener accepted a connection, the route selected the function, the function read query data, and the runtime sent its JSON response back to the client.

Terminal
hhy serve app.hhy
# In a second terminal:
curl "http://127.0.0.1:9316/hello?name=Ada"

Expect the JSON object shown at the beginning.

Separate common failure cases

If the request cannot connect, check whether the server is still running and whether the port matches the listener. If it connects but the path is unknown, investigate route registration and the URL. These are different failure layers and deserve different fixes. The supplied verifier checks the successful response and a missing route, then terminates only the server process it started. During manual practice, stop your server with Control C when you finish so a later run can bind the same port.

hhy
Wrong port  connection problem
Wrong path  route problem
Correct path + query  JSON response

The automated verifier also checks an unknown route.

Practice and finish the first section

Change the query name to Grace and predict the response before sending the request. Then add a message field to the returned object, restart the server, and verify the new output. Keep deployment, authentication, and more elaborate service architecture for a separate lesson. You now have the complete first section's toolkit: scripts, streams, files, data conversion, commands, HTTP clients, bounded parallelism, event driven work, and a small JSON API. Use the downloaded examples as starting points, and keep checking actual results as you adapt them.

hhy
Try /hello?name=Grace
Then add a message field to the response.

Keep the first exercise local and small.