forked from mirrors/kore
142 lines
3.9 KiB
C
142 lines
3.9 KiB
C
/*
|
|
* Copyright (c) 2019 Joris Vink <joris@coders.se>
|
|
*
|
|
* Permission to use, copy, modify, and distribute this software for any
|
|
* purpose with or without fee is hereby granted, provided that the above
|
|
* copyright notice and this permission notice appear in all copies.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
*/
|
|
|
|
/*
|
|
* This example demonstrates how easy it is to perform asynchronous
|
|
* HTTP client requests using the integrated libcurl support.
|
|
*
|
|
* In this example we setup 2 states for an HTTP request:
|
|
* 1) setup
|
|
* We initialize the HTTP request and fire it off.
|
|
* This will put our HTTP request to sleep and it be woken up
|
|
* by Kore when a response is available or something went wrong.
|
|
*
|
|
* 2) result
|
|
* After we have woken up we have access to the result.
|
|
*/
|
|
|
|
#include <kore/kore.h>
|
|
#include <kore/http.h>
|
|
#include <kore/curl.h>
|
|
|
|
int http(struct http_request *);
|
|
|
|
static int state_setup(struct http_request *);
|
|
static int state_result(struct http_request *);
|
|
|
|
/* Our states. */
|
|
static struct http_state states[] = {
|
|
KORE_HTTP_STATE(state_setup),
|
|
KORE_HTTP_STATE(state_result)
|
|
};
|
|
|
|
/* Transcend into the HTTP state machine for a request. */
|
|
int
|
|
http(struct http_request *req)
|
|
{
|
|
return (http_state_run(states, 2, req));
|
|
}
|
|
|
|
/*
|
|
* Setup the HTTP client request using the integrated curl API and the easy
|
|
* to use HTTP client api.
|
|
*/
|
|
static int
|
|
state_setup(struct http_request *req)
|
|
{
|
|
struct kore_curl *client;
|
|
|
|
client = http_state_create(req, sizeof(*client), NULL);
|
|
|
|
/* Initialize curl. */
|
|
if (!kore_curl_init(client, "https://kore.io", KORE_CURL_ASYNC)) {
|
|
http_response(req, 500, NULL, 0);
|
|
return (HTTP_STATE_COMPLETE);
|
|
}
|
|
|
|
/* Setup our HTTP client request. */
|
|
kore_curl_http_setup(client, HTTP_METHOD_GET, NULL, 0);
|
|
|
|
/* Add some headers. */
|
|
kore_curl_http_set_header(client, "x-source", "from-example");
|
|
|
|
/* We could opt to override some settings ourselves if we wanted. */
|
|
/* curl_easy_setopt(client->handle, CURLOPT_SSL_VERIFYHOST, 0); */
|
|
/* curl_easy_setopt(client->handle, CURLOPT_SSL_VERIFYPEER, 0); */
|
|
|
|
/*
|
|
* Bind the HTTP client request to our HTTP request so we get woken
|
|
* up once a response is available.
|
|
*
|
|
* This will put us to sleep.
|
|
*/
|
|
kore_curl_bind_request(client, req);
|
|
|
|
/*
|
|
* Now fire off the request onto the event loop.
|
|
*/
|
|
kore_curl_run(client);
|
|
|
|
/* Make sure we go onto the next state once woken up. */
|
|
req->fsm_state = 1;
|
|
|
|
/* Tell Kore we can't complete this immediately. */
|
|
return (HTTP_STATE_RETRY);
|
|
}
|
|
|
|
/*
|
|
* This state is called when a result for the HTTP request call is
|
|
* available to us.
|
|
*/
|
|
static int
|
|
state_result(struct http_request *req)
|
|
{
|
|
size_t len;
|
|
const u_int8_t *body;
|
|
const char *header;
|
|
struct kore_curl *client;
|
|
|
|
/* Get the state attached to the HTTP request. */
|
|
client = http_state_get(req);
|
|
|
|
/* Check if we were successful, if not log an error. */
|
|
if (!kore_curl_success(client)) {
|
|
kore_curl_logerror(client);
|
|
http_response(req, 500, NULL, 0);
|
|
} else {
|
|
/*
|
|
* Success! We now have the body available to us.
|
|
*/
|
|
kore_curl_response_as_bytes(client, &body, &len);
|
|
|
|
/* We could check the existence of a header: */
|
|
if (kore_curl_http_get_header(client, "server", &header))
|
|
printf("got server header: '%s'\n", header);
|
|
|
|
/*
|
|
* Respond to our client with the status and body from
|
|
* the HTTP client request we did.
|
|
*/
|
|
http_response(req, client->http.status, body, len);
|
|
}
|
|
|
|
/* Cleanup. */
|
|
kore_curl_cleanup(client);
|
|
|
|
/* State is now finished. */
|
|
return (HTTP_STATE_COMPLETE);
|
|
}
|