Skip to content

Latest commit

 

History

History
288 lines (207 loc) · 6.49 KB

http.md

File metadata and controls

288 lines (207 loc) · 6.49 KB

HTTP Module

The http module provides an HTTP client (GET, POST, PUT, DELETE) and an HTTP server with request routing. The client is backed by libcurl; the server uses libmicrohttpd.


Import

import http;

HTTP Client

Simple GET

string http.get(string url)

Performs an HTTP GET and returns the response body as a string.

string body = http.get("https://api.example.com/data");
output(body, string);

GET with custom headers

string http.get_headers(string url, dict headers)
dict headers = {"Authorization": "Bearer mytoken", "Accept": "application/json"};
string body = http.get_headers("https://api.example.com/protected", headers);
output(body, string);

POST

string http.post(string url, string body, dict headers)
dict headers = {"Content-Type": "application/json"};
string payload = "{\"name\": \"Alice\", \"age\": 30}";
string response = http.post("https://api.example.com/users", payload, headers);
output(response, string);

PUT

string http.put(string url, string body, dict headers)
dict headers = {"Content-Type": "application/json"};
string payload = "{\"age\": 31}";
string response = http.put("https://api.example.com/users/1", payload, headers);

DELETE

string http.delete(string url, dict headers)
dict headers = {};
string response = http.delete("https://api.example.com/users/1", headers);

Checking the status code

After any client request, call http.get_status_code() to get the HTTP status of the last response:

int http.get_status_code()
string response = http.get("https://api.example.com/item/999");
int status = http.get_status_code();
if (status == 404) {
    output("Not found", string);
} else if (status == 200) {
    output(response, string);
}

Getting response headers

dict http.get_response_headers()

Returns all response headers from the last request as a dictionary.

string body = http.get("https://api.example.com/data");
dict resp_headers = http.get_response_headers();
string content_type = dict_get(resp_headers, "content-type");
output(content_type, string);

Full response object

http.get_full() and http.post_full() return an opaque response pointer that includes the body, status code, and headers together. Free it when done:

ptr http.get_full(string url)
ptr http.post_full(string url, string body, dict headers)
void http.free_response(ptr response)

Use these when you need all three pieces atomically. For most cases, http.get() + http.get_status_code() is simpler.


HTTP Server

Handler function signature

An HTTP server requires a handler function that PIE passes to http.listen. The handler receives an opaque request and response pointer:

void myHandler(ptr req, ptr res) {
    // read the request
    string method = http.request_get_method(req);
    string path   = http.request_get_path(req);
    string body   = http.request_get_body(req);

    // write the response
    http.response_set_status(res, 200);
    http.response_set_header(res, "Content-Type", "text/plain");
    http.response_set_body(res, "Hello from PIE!");
}

Do not use dot notation on req/res directly — always use the module functions.


Starting the server

void http.listen(int port, ptr handler)

http.listen blocks forever, serving requests on the given port.

void main() {
    output("Listening on port 8080", string);
    http.listen(8080, myHandler);
}

HTTPS server

void http.listen_ssl(int port, string cert_file, string key_file, ptr handler)
http.listen_ssl(8443, "server.crt", "server.key", myHandler);

Request inspection functions

Function Signature Description
http.request_get_method string(ptr req) "GET", "POST", etc.
http.request_get_path string(ptr req) URL path, e.g. "/api/users"
http.request_get_body string(ptr req) Request body (for POST/PUT)
http.request_get_header string(ptr req, string name) Single request header by name
http.request_get_headers dict(ptr req) All request headers as a dict

Response writing functions

Function Signature Description
http.response_set_status void(ptr res, int code) HTTP status code (e.g. 200, 404)
http.response_set_body void(ptr res, string body) Response body
http.response_set_header void(ptr res, string name, string value) Add a response header

Complete Server Example

import http;
import json;

void handler(ptr req, ptr res) {
    string method = http.request_get_method(req);
    string path   = http.request_get_path(req);

    if (path == "/health") {
        http.response_set_status(res, 200);
        http.response_set_header(res, "Content-Type", "application/json");
        http.response_set_body(res, "{\"status\":\"ok\"}");
        return;
    }

    if (method == "POST" && path == "/echo") {
        string body = http.request_get_body(req);
        http.response_set_status(res, 200);
        http.response_set_header(res, "Content-Type", "text/plain");
        http.response_set_body(res, body);
        return;
    }

    // 404 fallback
    http.response_set_status(res, 404);
    http.response_set_body(res, "Not Found");
}

void main() {
    output("Server on port 8080", string);
    http.listen(8080, handler);
}

Complete Client Example

import http;
import json;

void main() {
    // GET request
    string raw = http.get("https://jsonplaceholder.typicode.com/todos/1");
    int status = http.get_status_code();

    if (status != 200) {
        output("Request failed", string);
        return;
    }

    json.object todo = json.parse(raw);
    int id        = json.get_int(todo, "id");
    string title  = json.get_string(todo, "title");
    int completed = json.get_bool(todo, "completed");

    output("Todo #" + int_to_string(id) + ": " + title, string);
    if (completed == 1) {
        output("Status: done", string);
    } else {
        output("Status: pending", string);
    }
}

See Also