lpereira/lwan

HTTP request to third party within a handler

lockie opened this issue · 4 comments

Hello. I'm trying to make an HTTP request to third party server within lwan handler code, which (I believe) should leverage event-based architecture putting the coroutine waiting for response to sleep and allowing other coroutines to do meaningful work. I'm using the following code (which is slightly modified asyncawait example):

static const char host[] = "httpbin.org";
static const char httpbin_request[] = "GET /delay/1 HTTP/1.0\r\n\r\n";

static void close_socket(void *data) { close((int)(intptr_t)data); }

LWAN_HANDLER(asyncawait)
{
    struct addrinfo* addr;
    int r = getaddrinfo(host, "http",
            &(struct addrinfo){.ai_family = AF_INET,
                               .ai_protocol = IPPROTO_TCP}, &addr);
    if (r != 0)
    {
        printf("getaddrinfo: %s\n", gai_strerror(r));
        return HTTP_INTERNAL_ERROR;
    }

    int fd = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
    if (fd < 0)
        return HTTP_INTERNAL_ERROR;

    coro_defer(request->conn->coro, close_socket, (void *)(intptr_t)fd);

    if (connect(fd, addr->ai_addr, addr->ai_addrlen) != 0)
    {
        perror("connect");
        return HTTP_INTERNAL_ERROR;
    }

    freeaddrinfo(addr);

    lwan_request_async_write(request, fd, httpbin_request,
                             sizeof(httpbin_request) - 1);

    while (true) {
        char buffer[128];
        ssize_t r = lwan_request_async_read(request, fd, buffer, sizeof(buffer));

        lwan_strbuf_set_static(response->buffer, buffer, (size_t)r);
        lwan_response_send_chunk(request);
    }

    return HTTP_OK;
}

However, this code demonstrates weird behaviour: I'm getting a few "Empty response from server" from curl, then after few retries I get expected response (some JSON from http://httpbin.org/delay/1), and after that lwan process gets stuck at 100% CPU on single core and all I'm getting from it is "Empty response from server".
Using Wireshark, I can see that the request being sent, and httpbin.org returns reponse, immediately closing connection afterwards. It feels like something fishy is going on in the read loop, is it some important coroutine-related detail I'm missing here?

Are you using an up-to-date Lwan? There was one change recently that should've fixed an issue similar to the "Empty reply from server" thing you've observed.

Oh nice, I've updated to latest master, and the issue went away. Thank you very much! 😊

Right, thanks for the tip!