Giter Club home page Giter Club logo

naett's Introduction

naett /nɛt:/

Tiny HTTP client library in C.

Wraps native HTTP client functionality on macOS, Windows, Linux, iOS and Android in a single, simple non-blocking API.

Using naett

Get the naett.c and naett.h files and throw them into your project. Check out the example for a basic Makefile - based setup.

The library needs to be initialized by a call to naettInit(). On Android, you need to provide a JavaVM* handle in the call to naettInit(). On the other platforms, call with NULL.

See naett.h for reference docs.

Platform implementations

naett uses the following HTTP client libraries on each platform:

Platform Library / component Build with
macOS, iOS NSURLRequest -framework Foundation
Windows WinHTTP Sessions -lwinhttp
Android java.net.URL NDK
Linux libcurl -lcurl -lpthread

Example

#include "naett.h"
#include <unistd.h>
#include <stdio.h>

int main(int argc, char** argv) {
    naettInit(NULL);

    naettReq* req =
        naettRequest("https://foo.site.net", naettMethod("GET"), naettHeader("accept", "application/json"));

    naettRes* res = naettMake(req);

    while (!naettComplete(res)) {
        usleep(100 * 1000);
    }

    if (naettGetStatus(res) < 0) {
        printf("Request failed\n");
        return 1;
    }

    int bodyLength = 0;
    const char* body = naettGetBody(res, &bodyLength);

    printf("Got %d bytes of type '%s':\n", bodyLength, naettGetHeader(res, "Content-Type"));
    printf("%.100s\n...\n", body);
}

naett's People

Contributors

erkkah avatar hrydgard avatar tjachmann avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

naett's Issues

probable error in unix version: numItems ignored in readCallBack

In the following code the argument numItems is ignored. In contrast, in the function writeCallback immediately following, it is multiplied by size.

naett/naett.c

Lines 836 to 840 in e44a499

static size_t readCallback(char* buffer, size_t size, size_t numItems, void* userData) {
InternalResponse* res = (InternalResponse*)userData;
InternalRequest* req = res->request;
return req->options.bodyReader(buffer, size, req->options.bodyReaderData);
}

Fix: replace line 839 with

return req->options.bodyReader(buffer, size * numItems, req->options.bodyReaderData);

extra info at end of URL not passed through in Windows

A URL like

http://localhost/maps/torridon.ctm1?type=metadata

does not work properly because the extra info '?type=metadata' is stripped from the URL in the Windows implementation of the Naett library.

The fix is to change this line:

naett/naett.c

Line 1198 in e44a499

req->resource = wcsndup(components.lpszUrlPath, components.dwUrlPathLength);

to

req->resource = wcsndup(components.lpszUrlPath, components.dwUrlPathLength + components.dwExtraInfoLength);

memory leaks: RequestOptions.method and InternalResponse.body.data not freed

I found copious memory leaks when using Naett in Windows. I was freeing up memory using naettFree for the naettReq object, and naettClose for the naettRes object,

The memory leaks can be fixed by adding free(req->options.method); to naettFree so that it becomes:

void naettFree(naettReq* request) {
    assert(request != NULL);

    InternalRequest* req = (InternalRequest*)request;
    naettPlatformFreeRequest(req);
    KVLink* node = req->options.headers;
    freeKVList(node);
    free((void*)req->url);
    free(req->options.method);
    free(request);
}

and adding free(res->body.data); to naettClose so that it becomes:

void naettClose(naettRes* response) {
    assert(response != NULL);

    InternalResponse* res = (InternalResponse*)response;
    res->request = NULL;
    naettPlatformCloseResponse(res);
    KVLink* node = res->headers;
    freeKVList(node);
    free(res->body.data);
    free(response);
}

String leak (userAgent)

At least on Windows, naett seems to leak some strings set by stringSetter.

Report after running (it just leaks the user agent string):

C:\dev\ppsspp\ext\naett\naett.c(154) : {4247868} normal block at 0x0000021496CEE120, 31 bytes long.
 Data: <PPSSPP/v1.16.5-1> 50 50 53 53 50 50 2F 76 31 2E 31 36 2E 35 2D 31 
C:\dev\ppsspp\ext\naett\naett.c(154) : {4243564} normal block at 0x0000021496CE9E00, 31 bytes long.
 Data: <PPSSPP/v1.16.5-1> 50 50 53 53 50 50 2F 76 31 2E 31 36 2E 35 2D 31 
C:\dev\ppsspp\ext\naett\naett.c(154) : {4241788} normal block at 0x0000021496CEE1E0, 31 bytes long.
 Data: <PPSSPP/v1.16.5-1> 50 50 53 53 50 50 2F 76 31 2E 31 36 2E 35 2D 31 
C:\dev\ppsspp\ext\naett\naett.c(154) : {4067325} normal block at 0x0000021496CE8D80, 31 bytes long.
 Data: <PPSSPP/v1.16.5-1> 50 50 53 53 50 50 2F 76 31 2E 31 36 2E 35 2D 31 

naett.c(154) is simply char* stringCopy = strdup(param->string);.

Android: Multiple definition of JNI_Onload

I'm already using a JNI_OnLoad in my app, so since naett defines one, I get a multiple definition error.

So what's needed is some way to pass your jni environment into naett, instead of having it try to grab it itself. Scratch that, I see that naettPlatformInit can already do it. So I only need to get rid of the extra JNI_OnLoad somehow.

Can we have a define maybe? #ifdef USE_EXISTING_JNI_ONLOAD for example.

use of wsprintfW causes Windows compilation to fail in Qt app

For some reason the function wsprintfW cannot be found and causes a link error when using the Naett library for a Windows Qt app. The function is used here:

wsprintfW(contentLengthHeader, L"Content-Length: %d", contentLength);

and of course in the amalgamation. The fix is to use the standard function swprintf and change the line of code to:

 swprintf(contentLengthHeader, 64, L"Content-Length: %d", contentLength);

missing call to DeleteLocalRef in Android code

This statement (as far as I understand the JNI) creates a local reference:

naett/naett.c

Line 1486 in cad8664

jobject values = call(env, headerMap, "get", "(Ljava/lang/Object;)Ljava/lang/Object;", name);

but it is not deleted, like the other local references, here:

naett/naett.c

Lines 1499 to 1500 in cad8664

(*env)->DeleteLocalRef(env, name);
(*env)->DeleteLocalRef(env, value);

The fix is to add the following statement at line 1501:

(*env)->DeleteLocalRef(env, values);

replace strdup with _strdup in Windows

Compilation in Visual Studio 2022 gives this warning:

warning C4996: 'strdup': The POSIX name for this item is deprecated. Instead, use the ISO C and C++ conformant name: _strdup.

The warning can be removed by adding the line

#define strdup _strdup

to this section of code:

naett/naett.c

Lines 8 to 12 in e44a499

#ifdef _MSC_VER
#define strcasecmp _stricmp
#define min(a,b) (((a)<(b))?(a):(b))
#endif

naettInit or naettOption for user agent?

I don't have access to my git version as a preprocessor variable that I can pass into naett in the build, but I do have it as a const char *. So I'd like to set a useragent based on it at runtime, either as a parameter for naettInit, or simply as a naettOption for each request (or ability to leave it out altogether so you can just set it with naettHeader).

I'm happy to do a PR, though it would probably be quicker for you to do it.

Cookie enable feature

plz add cookie support. enable, get and set cookie feature... like java cookieHandler and cookieManager.

incorrect use of DeleteLocalRef in Android code

The variable header is passed to DeleteLocalRef here:

(*env)->DeleteLocalRef(env, header);

and in the amalgamation:

naett/naett.c

Line 1495 in e44a499

(*env)->DeleteLocalRef(env, header);

The statement is incorrect, because header is of an invalid type

KVLink* header = req->options.headers;

I believe that it did not trigger an exception because header is always null when the incorrect statement is executed; but nevertheless it should be deleted.

Add getter for download progress?

It would be nice to check the progress of larger downloads.

Something like this:

	if (!naettComplete(res_)) {
		// Update progress
		int downloadedBytes = 0, totalBytes= 0;
		naettGetProgress(res_, &downloadedBytes , &totalBytes);
                // ...
	}

If the size is unknown, *totalSize would be set to -1.

I guess cleanest would be if naettComplete also had two output parameters, downloadedBytes and totalBytes.

Actually I guess this can be hacked by manually reading the Content-Length header, and then checking res->body.size.

Though it occurs to me that there's a data race - if I read headers while !completed, it may be that the headers are currently being filled in.

Here's my current hack that 'works' (doing the below if naettComplete() didn't return true) but has at least two races:

	const char *header = naettGetHeader(res_, "Content-Length");
	if (header) {
		strlcpy(buf, sizeof(buf), header);
		sscanf(buf, "%d", &total);
		int size;
		naettGetBody(res_, &size);
		progress_.Update(size, total);
	}

the timeout parameter is ignored in Windows

In the iOS, Linux and Android implementations the parameter timeoutMS in the RequestOptions structure is used to set the timeout. This parameter is ignored in the Windows implementation, causing different behaviour.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.