Accessing and passing query parameters

Hi, I am new to Zig and I was trying to understand how to manipulate query parameters in an http request, using the standard library.
I did not find any helping methods, as of the moment, am I supposed to manually process them in the URI?

Thank you for the help in advance

Hi @correia55
Welcome to ziggit :slight_smile:

No, there is no helper for parsing or setting GET uri query parameters or POST x-www-form-urlencoded parameters, in zig standard library.

You might find usefull: http.zig/src/params.zig at master · karlseguin/http.zig · GitHub

Thanks for the clarification and help :slight_smile:.

In the meantime, I’ve already created two helper functions for my use case:

const std = @import("std");

pub fn get_uri_without_query_parameters(raw_uri: []const u8) []const u8 {
    for (raw_uri, 0..) |c, i| {
        if (c == '?') {
            return raw_uri[0..i];
        }
    }

    return raw_uri;
}

pub fn get_query_parameters(allocator: std.mem.Allocator, raw_uri: []const u8) !std.hash_map.StringHashMap([]const u8) {
    var query_param_map = std.hash_map.StringHashMap([]const u8).init(allocator);

    var query_section_started = false;

    var capture_start: u32 = undefined;
    var param_name: ?[]const u8 = null;

    for (raw_uri, 0..) |c, i| {
        const i_u32: u32 = @intCast(i);

        if (c == '?') {
            query_section_started = true;

            // Start capturing the parameter name
            capture_start = i_u32 + 1;

            continue;
        }

        if (!query_section_started) {
            continue;
        }

        // Assumes the capture needs to be at least one character long
        if (i == capture_start) {
            continue;
        }

        if (c == '=') {
            if (param_name != null) {
                return std.Uri.ParseError.UnexpectedCharacter;
            }

            // Complete the parameter name
            param_name = raw_uri[capture_start..i_u32];

            // Start capturing the parameter value
            capture_start = i_u32 + 1;
        }

        if (c == '&') {
            if (param_name == null) {
                return std.Uri.ParseError.UnexpectedCharacter;
            }

            // Add the pair
            try query_param_map.put(param_name.?, raw_uri[capture_start..i_u32]);

            // Start capturing a new parameter name
            capture_start = i_u32 + 1;
            param_name = null;

            continue;
        }
    }

    // Take care of the last query parameter
    if (param_name != null) {
        try query_param_map.put(param_name.?, raw_uri[capture_start..]);
    }

    return query_param_map;
}

Do you think this could be a useful addition to the standard library (I’m sure it can be improved upon) ?
If so, any tips on what to do, or would I just open a pull request ?

1 Like