{"_id":"588f722cbcace50f0052ba1b","parentDoc":null,"__v":0,"user":"565f5f29de5dc50d00acfe9f","version":{"_id":"588f722bbcace50f0052b9e1","project":"565f5fa26bafd40d0030a064","__v":1,"createdAt":"2017-01-30T17:04:43.410Z","releaseDate":"2017-01-30T17:04:43.410Z","categories":["588f722bbcace50f0052b9e2","588f722bbcace50f0052b9e3","588f722bbcace50f0052b9e4","588f722bbcace50f0052b9e5","588f722bbcace50f0052b9e6","588f722bbcace50f0052b9e7"],"is_deprecated":false,"is_hidden":false,"is_beta":false,"is_stable":true,"codename":"","version_clean":"5.3.0","version":"5.3.0"},"category":{"_id":"588f722bbcace50f0052b9e5","version":"588f722bbcace50f0052b9e1","__v":0,"project":"565f5fa26bafd40d0030a064","sync":{"url":"","isSync":false},"reference":false,"createdAt":"2016-02-18T20:31:28.395Z","from_sync":false,"order":3,"slug":"sdks","title":"Client SDKs"},"project":"565f5fa26bafd40d0030a064","updates":["57e54a6f00c8680e00fae7d4","57ea8c73802e4a17009181ac"],"next":{"pages":[],"description":""},"createdAt":"2016-05-19T14:11:54.994Z","link_external":false,"link_url":"","githubsync":"","sync_unique":"","hidden":false,"api":{"results":{"codes":[]},"settings":"","auth":"required","params":[],"url":""},"isReference":false,"order":5,"body":"The nanoscale.io C SDK is a lightweight SDK written in C. It can be used to connect a client to a nanoscale.io gateway. You can view the source <a href=\"https://github.com/nanoscaleio/justapis-c-sdk\" target=\"_blank\">here on GitHub</a>.\n\n##Dependencies\n\n### Development/Production\n\n* **CMake 3.5** [Optional, build tool] To build and use the SDK as a static library, you'll need CMake 3.5 or higher.\nHowever, you can also include the SDK in your own project simply by including the contents of both the src and include\ndirectories and making sure you link against libcurl.\n\n* **libcurl** [Required, library] The SDK currently relies extensively on libcurl for cross-platform HTTP communication.\nYou will need to make sure that the development libraries and headers for libcurl are available to\nthe compiler and linker when building a project that uses this SDK. CMake will find the libcurl development\nitems automatically if they're installed on your system.\n\n* **cJSON** [Optional, source included] The SDK can *optionally* provide simple JSON serialization when sending\nrequests, and JSON deserialization when receiving responses. This feature is enabled by default and the source code\nfor cJSON (`cJSON.h` and `cJSON.c`) is included and built into the library automatically.\n\n\n### Unit Testing\n\nUnit testing is implemented for this project as a secondary target `runTests` in the CMake listfile. It uses and\nand includes `CHEAT` as a testing framework and `Civetweb` to mock a nanoscale.io HTTP gateway. As long as you meet\nthe requirements for the SDK, above, no further dependencies are needed for testing.\n\n## Introduction\n\nThe core of the SDK is provided in the following files:\n\n * `include/justapis.h`\n * `src/justapis.c`\n\nOptional JSON support is provided using cJSON:\n\n * `include/cJSON.h`\n * `src/cJSON.c`\n\nHTTP requests are handled through **libcurl**.\n\nYou may build, install, and test the SDK as a library using CMake, or include the above files directly in your own\nproject that links against libcurl.\n\nThree structs capture the core concepts of the SDK: `ja_gateway`, `ja_request`, and `ja_response`.\n\nA `ja_gateway` represents a specific nanoscale.io gateway instance and session. You submit `ja_request`s to this gateway,\nand receive `ja_respose`s or errors in response.\n\nThe following features are supported:\n\n* The `ja_gateway` can optionally persist cookies across requests, and even across instances and runs,\nusing a cookiejar file.\n* The `ja_gateway` can optionally provide a response cache, allowing repeated requests to return a cached response\nwithout making an additional network request.\n* The `ja_gateway` can have default Query Parameters and HTTP Headers which will get appended to all outgoing requests. This can be\nuseful for authentication tokens. Individual requests can override the default values with specific values of their own.\n* The `ja_gateway` can have default callbacks to use when sending body data with requests, receiving body data in\nresponses, or receiving headers. Alternative callbacks be supplied when performing a request. If no callbacks are\nprovided the SDK provides can manage these operations automatically using simple in-memory buffers for body data and\nstandard parsing of headers.\n* With cJSON included, and JA_ENABLE_CJSON set to a non-zero value (default), the SDK can automaticaly serialize\nJSON objects to send in the body of requests, and can automatically deserialize JSON content that's received in responses.\n* The entire SDK can use custom memory allocator functions that match the function signature of the stdlib allocator\nfunctions. If no custom allocators are provided, stdlib `malloc`, `realloc`, `calloc`, `strdup`, and `free` will be\nused by default.\n\n##Setup\n\n### Installing Dependencies\n\nThe dependencies of this SDK are described above. You'll need libcurl installed and built for your system, cJSON\n(included) if you want JSON support, and CMake if you want to build and test the SDK as a library.\n\n#### CMake\n\nYou can get CMake from [here](https://cmake.org/download). To use it with this project, you'll need version 3.5 or above.\n\n#### libcurl\n\nMany OS package managers can install libcurl. However, make sure that you install the development headers. For instance,\non Raspberry Pi Raspian, and other Debian-like systems, you'll want to install:\n\n```bash\n> apt-get install libcurl4-dev\n```\n\nOf course, you can also download and install libcurl directly from\nits [developer site](https://curl.haxx.se/download.html).\n\n### Using the SDK as a Library\n\n1. Use CMake to make your platform-specific build system.\n2. Invoke that build system to build and install the SDK library\n3. Link against that library (`justapis-c-sdk`) in your own project.\n\n### Including Code Directly\n\nThe SDK is intentionally organized in a way that makes it easy for you to include it in your own project without linking\nit in as a library or relying on CMake.\n\nTo take advantage of this, just include the following 4 files in your project and make sure to link against libcurl:\n\n* `justapis.h`\n* `justapis.c`\n* `cJSON.h`\n* `cJSON.c`\n\nYou can optionally exclude the cJSON files if you don't want to use JSON or will be managing serialization and\ndeserialization of JSON in your own code. If you do exclude these files, make sure to set the build flag\n`JA_ENABLE_CJSON` to `0`.\n\n## Usage\n\n### Making requests\n\nTo make requests to your nanoscale.io server, you'll just need to create a `ja_gateway`, submit a `ja_request`.\n\nA simple example is shown here: \n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"// Create the gateway. Using NULL for the second parameter disables cookie support.\\nja_gateway* gateway = ja_gateway_init(\\\"http://my-nanoscale-server.local:5000/\\\", NULL);\\n\\n// Create a request to GET /foo\\nja_request* request = ja_request_init(ja_request_method_get, \\\"/foo\\\");\\n\\n// Add a query parameter\\nja_request_set_query_parameter(request, \\\"id\\\", \\\"123\\\");\\n\\n// Perform the request. Using NULL for the third parameter indicates we don't need custom body/header callbacks.\\nja_result result = ja_perform_request(gateway, request, NULL);\\n\\n// Inspect the result\\nif (result.error != ja_request_error_none)\\n{\\n    // Anything but ja_request_error_none indicates an error.\\n    printf(\\\"Received an error: %d\\\", result.error);\\n}\\nelse\\n{\\n    // If there was no error, there should be a response. Report its status code\\n    printf(\\\"Received a response with HTTP status code: %ld\\\", result.response.status_code);\\n\\n    // Clean up the response, since we're done with it.\\n    ja_response_free(result.response);\\n}\\n\\n// Clean up the request\\nja_request_free(request);\\n\\n// Clean up the gateway\\nja_gateway_free(gateway);\\n\",\n      \"language\": \"c\",\n      \"name\": \"Request\"\n    }\n  ]\n}\n[/block]\n### Response Caching\n\nResponse caching is disabled by default.\n\nTo use it, you must first enable the gateway's cache:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"// Enable caching of up to 25 distinct responses:\\nja_gateway_enable_cache(gateway, 25);\",\n      \"language\": \"c\",\n      \"name\": \"Response caching\"\n    }\n  ]\n}\n[/block]\nLater, make you can describe your cache preferences when making a GET request:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"// Allow the cache to service this request, if a response is found.\\nrequest.allow_cached_response = true;\\n\\n// If this request hits the network, specify how long to save its response in the cache\\nrequest.cache_response_with_expiration = 30; // seconds\\n\\n// When working with the cache, use the following cache identifier rather than the URL-based hash:\\nrequest.custom_cache_identifier = 0xdeadbeef;\",\n      \"language\": \"c\",\n      \"name\": \"GET request\"\n    }\n  ]\n}\n[/block]\n### Receiving JSON Responses\n\nBy default automatic JSON parsing is available, but disabled.\n\nTo enable it on a specific request:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"request.parse_json_responses_automatically = true;\",\n      \"language\": \"c\",\n      \"name\": \"JSON parsing\"\n    }\n  ]\n}\n[/block]\nIf that flag is set and the SDK encounters a Content-Type of `application/json` or `text/json` in response to a request,\nyou can access the parsed JSON data as follows:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"if (response.body_type == ja_response_body_type_json)\\n{\\n    cJSON* json = response.json;\\n}\",\n      \"language\": \"c\",\n      \"name\": \"JSON response\"\n    }\n  ]\n}\n[/block]\n### Cookies\n\nCookie support is provided by libcurl through cookiejar files. To enable cookies on a gateway, provide a path for curl\nto use:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"// Create a temp file and get its path using mkstemp\\nchar cookiejar_path[L_tmpnam];\\nmemset(cookiejar_path, 0, sizeof(cookiejar_path));\\nsnprintf(cookiejar_path, L_tmpnam, \\\"%scookierjar.txt-XXXXXX\\\", P_tmpdir);\\nmkstemp(cookiejar_path);\\n\\n// Create the gateway and give it a cookiejar to store cookies\\ngateway = ja_gateway_init(\\\"http://localhost:31337\\\", cookiejar_path);\",\n      \"language\": \"c\",\n      \"name\": \"Cookies\"\n    }\n  ]\n}\n[/block]\n### Sending Body Data\n\nOn POST and PUT requests, you'll often want to send body data as part of those requests.\n\nYou always have the option to set binary body data yourself using `ja_request_set_body`. Make sure to set a\nContent-Type header on the request as well!\n\nIf you've left JSON support enabled, you can alternatively use `ja_request_set_json_body` which will automatically\nserialize your cJSON structure and set the Content-Type header appropriately.\n\n### Pinning Public Keys for HTTPS\n\nYou may want to verify that you're connecting to the expected gateway when using HTTPS by specifying the public key you\nexpect the server to report when the secure connection is made.\n\nTo do so, provide the expected public key using the `ja_gateway_set_pinned_public_key_file` function before submitting\nany requests. You may provide a path to a PEM or DER file, or a specially formatted string of sha256 hashes. For more\ninformation on support formats for the key, see the libcurl documentation for\n[CURLOPT_PINNEDPUBLICKEY](https://curl.haxx.se/libcurl/c/CURLOPT_PINNEDPUBLICKEY.html).\n\n### Memory Allocation\n\nThe SDK and libcurl manage memory using the stdlib function by default.\n\nIf you want the SDK to use different functions, provide them as follows:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"// Instruct the SDK (and cJSON) to use custom allocators\\nja_set_allocators(my_malloc, my_free, my_realloc, my_strdup, my_calloc);\",\n      \"language\": \"c\",\n      \"name\": \"Memory allocation\"\n    }\n  ]\n}\n[/block]\n**Note**: libcurl's allocators are NOT automatically changed when calling this method. If you need libcurl to use custom\nallocators as well, you'll want to call libcurl's own configuration function:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"curl_global_init_mem(my_malloc, my_free, my_realloc, my_strdup, my_calloc);\",\n      \"language\": \"c\",\n      \"name\": \"libcurl\"\n    }\n  ]\n}\n[/block]\nSee [https://curl.haxx.se/libcurl/c/curl_global_init_mem.html] for more information on that function.\n\n### Streamlining the Build\n\nBy default, the SDK builds in support for JSON,  Response Caching and Public Key Pinning. If you won't be using these,\nyou can reduce the size of the library by disabling each of them with a build flag.\n\nMake sure to set the build flag to `0` to disable the feature. Any non-zero value will leave the feature enabled,\nas will failure to set the flag at all.\n\n* To disable JSON support, set `JA_ENABLE_CJSON` to `0`\n* To disable Caching support, set `JA_ENABLE_RESPONSE_CACHING` to `0`\n* To disable Public Key Pinning support, set `JA_ENABLE_PUBLIC_KEY_PINNING` to `0`\n\n##Development\n\nYou can clone or fork this repository to make any changes you need to the source code or CMake listfiles for building\nprojects.\n\nYou can also include the source files directly into your own project and edit them there.","excerpt":"","slug":"c","type":"basic","title":"C"}
The nanoscale.io C SDK is a lightweight SDK written in C. It can be used to connect a client to a nanoscale.io gateway. You can view the source <a href="https://github.com/nanoscaleio/justapis-c-sdk" target="_blank">here on GitHub</a>. ##Dependencies ### Development/Production * **CMake 3.5** [Optional, build tool] To build and use the SDK as a static library, you'll need CMake 3.5 or higher. However, you can also include the SDK in your own project simply by including the contents of both the src and include directories and making sure you link against libcurl. * **libcurl** [Required, library] The SDK currently relies extensively on libcurl for cross-platform HTTP communication. You will need to make sure that the development libraries and headers for libcurl are available to the compiler and linker when building a project that uses this SDK. CMake will find the libcurl development items automatically if they're installed on your system. * **cJSON** [Optional, source included] The SDK can *optionally* provide simple JSON serialization when sending requests, and JSON deserialization when receiving responses. This feature is enabled by default and the source code for cJSON (`cJSON.h` and `cJSON.c`) is included and built into the library automatically. ### Unit Testing Unit testing is implemented for this project as a secondary target `runTests` in the CMake listfile. It uses and and includes `CHEAT` as a testing framework and `Civetweb` to mock a nanoscale.io HTTP gateway. As long as you meet the requirements for the SDK, above, no further dependencies are needed for testing. ## Introduction The core of the SDK is provided in the following files: * `include/justapis.h` * `src/justapis.c` Optional JSON support is provided using cJSON: * `include/cJSON.h` * `src/cJSON.c` HTTP requests are handled through **libcurl**. You may build, install, and test the SDK as a library using CMake, or include the above files directly in your own project that links against libcurl. Three structs capture the core concepts of the SDK: `ja_gateway`, `ja_request`, and `ja_response`. A `ja_gateway` represents a specific nanoscale.io gateway instance and session. You submit `ja_request`s to this gateway, and receive `ja_respose`s or errors in response. The following features are supported: * The `ja_gateway` can optionally persist cookies across requests, and even across instances and runs, using a cookiejar file. * The `ja_gateway` can optionally provide a response cache, allowing repeated requests to return a cached response without making an additional network request. * The `ja_gateway` can have default Query Parameters and HTTP Headers which will get appended to all outgoing requests. This can be useful for authentication tokens. Individual requests can override the default values with specific values of their own. * The `ja_gateway` can have default callbacks to use when sending body data with requests, receiving body data in responses, or receiving headers. Alternative callbacks be supplied when performing a request. If no callbacks are provided the SDK provides can manage these operations automatically using simple in-memory buffers for body data and standard parsing of headers. * With cJSON included, and JA_ENABLE_CJSON set to a non-zero value (default), the SDK can automaticaly serialize JSON objects to send in the body of requests, and can automatically deserialize JSON content that's received in responses. * The entire SDK can use custom memory allocator functions that match the function signature of the stdlib allocator functions. If no custom allocators are provided, stdlib `malloc`, `realloc`, `calloc`, `strdup`, and `free` will be used by default. ##Setup ### Installing Dependencies The dependencies of this SDK are described above. You'll need libcurl installed and built for your system, cJSON (included) if you want JSON support, and CMake if you want to build and test the SDK as a library. #### CMake You can get CMake from [here](https://cmake.org/download). To use it with this project, you'll need version 3.5 or above. #### libcurl Many OS package managers can install libcurl. However, make sure that you install the development headers. For instance, on Raspberry Pi Raspian, and other Debian-like systems, you'll want to install: ```bash > apt-get install libcurl4-dev ``` Of course, you can also download and install libcurl directly from its [developer site](https://curl.haxx.se/download.html). ### Using the SDK as a Library 1. Use CMake to make your platform-specific build system. 2. Invoke that build system to build and install the SDK library 3. Link against that library (`justapis-c-sdk`) in your own project. ### Including Code Directly The SDK is intentionally organized in a way that makes it easy for you to include it in your own project without linking it in as a library or relying on CMake. To take advantage of this, just include the following 4 files in your project and make sure to link against libcurl: * `justapis.h` * `justapis.c` * `cJSON.h` * `cJSON.c` You can optionally exclude the cJSON files if you don't want to use JSON or will be managing serialization and deserialization of JSON in your own code. If you do exclude these files, make sure to set the build flag `JA_ENABLE_CJSON` to `0`. ## Usage ### Making requests To make requests to your nanoscale.io server, you'll just need to create a `ja_gateway`, submit a `ja_request`. A simple example is shown here: [block:code] { "codes": [ { "code": "// Create the gateway. Using NULL for the second parameter disables cookie support.\nja_gateway* gateway = ja_gateway_init(\"http://my-nanoscale-server.local:5000/\", NULL);\n\n// Create a request to GET /foo\nja_request* request = ja_request_init(ja_request_method_get, \"/foo\");\n\n// Add a query parameter\nja_request_set_query_parameter(request, \"id\", \"123\");\n\n// Perform the request. Using NULL for the third parameter indicates we don't need custom body/header callbacks.\nja_result result = ja_perform_request(gateway, request, NULL);\n\n// Inspect the result\nif (result.error != ja_request_error_none)\n{\n // Anything but ja_request_error_none indicates an error.\n printf(\"Received an error: %d\", result.error);\n}\nelse\n{\n // If there was no error, there should be a response. Report its status code\n printf(\"Received a response with HTTP status code: %ld\", result.response.status_code);\n\n // Clean up the response, since we're done with it.\n ja_response_free(result.response);\n}\n\n// Clean up the request\nja_request_free(request);\n\n// Clean up the gateway\nja_gateway_free(gateway);\n", "language": "c", "name": "Request" } ] } [/block] ### Response Caching Response caching is disabled by default. To use it, you must first enable the gateway's cache: [block:code] { "codes": [ { "code": "// Enable caching of up to 25 distinct responses:\nja_gateway_enable_cache(gateway, 25);", "language": "c", "name": "Response caching" } ] } [/block] Later, make you can describe your cache preferences when making a GET request: [block:code] { "codes": [ { "code": "// Allow the cache to service this request, if a response is found.\nrequest.allow_cached_response = true;\n\n// If this request hits the network, specify how long to save its response in the cache\nrequest.cache_response_with_expiration = 30; // seconds\n\n// When working with the cache, use the following cache identifier rather than the URL-based hash:\nrequest.custom_cache_identifier = 0xdeadbeef;", "language": "c", "name": "GET request" } ] } [/block] ### Receiving JSON Responses By default automatic JSON parsing is available, but disabled. To enable it on a specific request: [block:code] { "codes": [ { "code": "request.parse_json_responses_automatically = true;", "language": "c", "name": "JSON parsing" } ] } [/block] If that flag is set and the SDK encounters a Content-Type of `application/json` or `text/json` in response to a request, you can access the parsed JSON data as follows: [block:code] { "codes": [ { "code": "if (response.body_type == ja_response_body_type_json)\n{\n cJSON* json = response.json;\n}", "language": "c", "name": "JSON response" } ] } [/block] ### Cookies Cookie support is provided by libcurl through cookiejar files. To enable cookies on a gateway, provide a path for curl to use: [block:code] { "codes": [ { "code": "// Create a temp file and get its path using mkstemp\nchar cookiejar_path[L_tmpnam];\nmemset(cookiejar_path, 0, sizeof(cookiejar_path));\nsnprintf(cookiejar_path, L_tmpnam, \"%scookierjar.txt-XXXXXX\", P_tmpdir);\nmkstemp(cookiejar_path);\n\n// Create the gateway and give it a cookiejar to store cookies\ngateway = ja_gateway_init(\"http://localhost:31337\", cookiejar_path);", "language": "c", "name": "Cookies" } ] } [/block] ### Sending Body Data On POST and PUT requests, you'll often want to send body data as part of those requests. You always have the option to set binary body data yourself using `ja_request_set_body`. Make sure to set a Content-Type header on the request as well! If you've left JSON support enabled, you can alternatively use `ja_request_set_json_body` which will automatically serialize your cJSON structure and set the Content-Type header appropriately. ### Pinning Public Keys for HTTPS You may want to verify that you're connecting to the expected gateway when using HTTPS by specifying the public key you expect the server to report when the secure connection is made. To do so, provide the expected public key using the `ja_gateway_set_pinned_public_key_file` function before submitting any requests. You may provide a path to a PEM or DER file, or a specially formatted string of sha256 hashes. For more information on support formats for the key, see the libcurl documentation for [CURLOPT_PINNEDPUBLICKEY](https://curl.haxx.se/libcurl/c/CURLOPT_PINNEDPUBLICKEY.html). ### Memory Allocation The SDK and libcurl manage memory using the stdlib function by default. If you want the SDK to use different functions, provide them as follows: [block:code] { "codes": [ { "code": "// Instruct the SDK (and cJSON) to use custom allocators\nja_set_allocators(my_malloc, my_free, my_realloc, my_strdup, my_calloc);", "language": "c", "name": "Memory allocation" } ] } [/block] **Note**: libcurl's allocators are NOT automatically changed when calling this method. If you need libcurl to use custom allocators as well, you'll want to call libcurl's own configuration function: [block:code] { "codes": [ { "code": "curl_global_init_mem(my_malloc, my_free, my_realloc, my_strdup, my_calloc);", "language": "c", "name": "libcurl" } ] } [/block] See [https://curl.haxx.se/libcurl/c/curl_global_init_mem.html] for more information on that function. ### Streamlining the Build By default, the SDK builds in support for JSON, Response Caching and Public Key Pinning. If you won't be using these, you can reduce the size of the library by disabling each of them with a build flag. Make sure to set the build flag to `0` to disable the feature. Any non-zero value will leave the feature enabled, as will failure to set the flag at all. * To disable JSON support, set `JA_ENABLE_CJSON` to `0` * To disable Caching support, set `JA_ENABLE_RESPONSE_CACHING` to `0` * To disable Public Key Pinning support, set `JA_ENABLE_PUBLIC_KEY_PINNING` to `0` ##Development You can clone or fork this repository to make any changes you need to the source code or CMake listfiles for building projects. You can also include the source files directly into your own project and edit them there.