Filling in more of http_request
This commit is contained in:
parent
b133a703cc
commit
c54cf989c0
4 changed files with 221 additions and 44 deletions
65
core/api.c
65
core/api.c
|
@ -333,6 +333,20 @@ struct ApiConnectionParam {
|
||||||
struct IpfsNode* this_node;
|
struct IpfsNode* this_node;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/***
|
||||||
|
* Take an s_request and turn it into an HttpRequest
|
||||||
|
* @param req the incoming s_request
|
||||||
|
* @returns the resultant HttpRequest or NULL on error
|
||||||
|
*/
|
||||||
|
struct HttpRequest* api_build_http_request(struct s_request* req) {
|
||||||
|
struct HttpRequest* request = ipfs_core_http_request_new();
|
||||||
|
if (request != NULL) {
|
||||||
|
request->command = req->buf + req->method;
|
||||||
|
//TODO: Complete this method
|
||||||
|
}
|
||||||
|
return request;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pthread to take care of each client connection.
|
* Pthread to take care of each client connection.
|
||||||
* @param ptr an ApiConnectionParam
|
* @param ptr an ApiConnectionParam
|
||||||
|
@ -420,11 +434,10 @@ void *api_connection_thread (void *ptr)
|
||||||
goto quit;
|
goto quit;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct HttpRequest* http_request = ipfs_core_http_request_new();
|
// once we leave the building of the req struct, do we need to do more? This flag will tell us.
|
||||||
|
int further_processing_necessary = 1;
|
||||||
|
|
||||||
if (strcmp(buf + req.method, "GET")==0) {
|
if (strcmp(buf + req.method, "GET")==0) {
|
||||||
char *path;
|
|
||||||
unsigned char *obj;
|
|
||||||
size_t size;
|
|
||||||
|
|
||||||
if (strcmp (req.buf + req.path, "/")==0 ||
|
if (strcmp (req.buf + req.path, "/")==0 ||
|
||||||
strcmp (req.buf + req.path, "/webui") ||
|
strcmp (req.buf + req.path, "/webui") ||
|
||||||
|
@ -441,23 +454,13 @@ void *api_connection_thread (void *ptr)
|
||||||
} else {
|
} else {
|
||||||
write_cstr (s, HTTP_500);
|
write_cstr (s, HTTP_500);
|
||||||
}
|
}
|
||||||
|
further_processing_necessary = 0;
|
||||||
} else {
|
} else {
|
||||||
//TODO: build http_request here
|
// move out of the if to do further processing
|
||||||
path = req.buf + req.path;
|
|
||||||
|
|
||||||
if (get_object(params->this_node, path, &obj, &size)) {
|
|
||||||
if (!send_object(s, obj, size)) {
|
|
||||||
libp2p_logger_error("api", "fail send_object.\n");
|
|
||||||
}
|
|
||||||
free(obj);
|
|
||||||
} else {
|
|
||||||
// object not found.
|
|
||||||
write_dual (s, req.buf + req.http_ver, strchr (HTTP_404, ' '));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
// end of GET
|
||||||
} else if (strcmp(buf + req.method, "POST")==0) {
|
} else if (strcmp(buf + req.method, "POST")==0) {
|
||||||
// TODO: Handle gzip/json POST requests.
|
// TODO: Handle gzip/json POST requests.
|
||||||
// TODO: build http_request here
|
|
||||||
|
|
||||||
p = header_value_cmp(&req, "Content-Type:", "multipart/form-data;");
|
p = header_value_cmp(&req, "Content-Type:", "multipart/form-data;");
|
||||||
if (p) {
|
if (p) {
|
||||||
|
@ -490,39 +493,51 @@ void *api_connection_thread (void *ptr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// TODO: Parse the path var and decide what to do with the received data.
|
|
||||||
if (req.boundary > 0) {
|
if (req.boundary > 0) {
|
||||||
libp2p_logger_error("api", "boundary index = %d, size = %d\n", req.boundary, req.boundary_size);
|
libp2p_logger_error("api", "boundary index = %d, size = %d\n", req.boundary, req.boundary_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
libp2p_logger_error("api", "method = '%s'\n"
|
libp2p_logger_debug("api", "method = '%s'\n"
|
||||||
"path = '%s'\n"
|
"path = '%s'\n"
|
||||||
"http_ver = '%s'\n"
|
"http_ver = '%s'\n"
|
||||||
"header {\n%s\n}\n"
|
"header {\n%s\n}\n"
|
||||||
"body_size = %d\n",
|
"body_size = %d\n",
|
||||||
req.buf+req.method, req.buf+req.path, req.buf+req.http_ver,
|
req.buf+req.method, req.buf+req.path, req.buf+req.http_ver,
|
||||||
req.buf+req.header, req.body_size);
|
req.buf+req.header, req.body_size);
|
||||||
|
// end of POST
|
||||||
|
} else {
|
||||||
|
// Unexpected???
|
||||||
|
libp2p_logger_error("api", "fail unexpected '%s'.\n", req.buf + req.method);
|
||||||
|
write_cstr (s, HTTP_500);
|
||||||
|
further_processing_necessary = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (further_processing_necessary) {
|
||||||
|
// now do something with the request we have built
|
||||||
|
struct HttpRequest* http_request = api_build_http_request(&req);
|
||||||
|
if (http_request != NULL) {
|
||||||
char* response_text = NULL;
|
char* response_text = NULL;
|
||||||
if (!ipfs_core_http_request_process(http_request, &response_text)) {
|
if (!ipfs_core_http_request_process(params->this_node, http_request, &response_text)) {
|
||||||
libp2p_logger_error("api", "ipfs_core_http_request_process returned false.\n");
|
libp2p_logger_error("api", "ipfs_core_http_request_process returned false.\n");
|
||||||
// TODO: Handle this condition
|
// TODO: Handle this condition
|
||||||
}
|
}
|
||||||
ipfs_core_http_request_free(http_request);
|
ipfs_core_http_request_free(http_request);
|
||||||
|
// now send the results
|
||||||
snprintf(resp, sizeof(resp), "%s 200 OK\r\n" \
|
snprintf(resp, sizeof(resp), "%s 200 OK\r\n" \
|
||||||
"Content-Type: application/json\r\n"
|
"Content-Type: application/json\r\n"
|
||||||
"Server: c-ipfs/0.0.0-dev\r\n"
|
"Server: c-ipfs/0.0.0-dev\r\n"
|
||||||
"X-Chunked-Output: 1\r\n"
|
"X-Chunked-Output: 1\r\n"
|
||||||
"Connection: close\r\n"
|
"Connection: close\r\n"
|
||||||
"Transfer-Encoding: chunked\r\n\r\n%s", req.buf + req.http_ver, response_text);
|
"Transfer-Encoding: chunked\r\n\r\n%s", req.buf + req.http_ver, response_text);
|
||||||
|
if (response_text != NULL)
|
||||||
free(response_text);
|
free(response_text);
|
||||||
write_str (s, resp);
|
write_str (s, resp);
|
||||||
libp2p_logger_error("api", "resp = {\n%s\n}\n", resp);
|
libp2p_logger_debug("api", "resp = {\n%s\n}\n", resp);
|
||||||
} else {
|
} else {
|
||||||
// Unexpected???
|
// uh oh... something went wrong converting to the HttpRequest struct
|
||||||
libp2p_logger_error("api", "fail unexpected '%s'.\n", req.buf + req.method);
|
libp2p_logger_error("api", "Unable to build HttpRequest struct.\n");
|
||||||
write_cstr (s, HTTP_500);
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
libp2p_logger_error("api", "fail looking for body.\n");
|
libp2p_logger_error("api", "fail looking for body.\n");
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
#include "libp2p/utils/vector.h"
|
#include "libp2p/utils/vector.h"
|
||||||
|
#include "libp2p/utils/logger.h"
|
||||||
#include "ipfs/core/http_request.h"
|
#include "ipfs/core/http_request.h"
|
||||||
|
#include "ipfs/namesys/resolver.h"
|
||||||
|
#include "ipfs/namesys/publisher.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles HttpRequest and HttpParam
|
* Handles HttpRequest and HttpParam
|
||||||
|
@ -27,10 +31,10 @@ struct HttpRequest* ipfs_core_http_request_new() {
|
||||||
*/
|
*/
|
||||||
void ipfs_core_http_request_free(struct HttpRequest* request) {
|
void ipfs_core_http_request_free(struct HttpRequest* request) {
|
||||||
if (request != NULL) {
|
if (request != NULL) {
|
||||||
if (request->command != NULL)
|
//if (request->command != NULL)
|
||||||
free(request->command);
|
// free(request->command);
|
||||||
if (request->sub_command != NULL)
|
//if (request->sub_command != NULL)
|
||||||
free(request->sub_command);
|
// free(request->sub_command);
|
||||||
if (request->params != NULL) {
|
if (request->params != NULL) {
|
||||||
for(int i = 0; i < request->params->total; i++) {
|
for(int i = 0; i < request->params->total; i++) {
|
||||||
struct HttpParam* curr_param = (struct HttpParam*) libp2p_utils_vector_get(request->params, i);
|
struct HttpParam* curr_param = (struct HttpParam*) libp2p_utils_vector_get(request->params, i);
|
||||||
|
@ -75,12 +79,147 @@ void ipfs_core_http_param_free(struct HttpParam* param) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/***
|
||||||
|
* Handle processing of the "name" command
|
||||||
|
* @param local_node the context
|
||||||
|
* @param request the incoming request
|
||||||
|
* @param response the response
|
||||||
|
* @returns true(1) on success, false(0) otherwise
|
||||||
|
*/
|
||||||
|
int ipfs_core_http_process_name(struct IpfsNode* local_node, struct HttpRequest* request, char** response) {
|
||||||
|
int retVal = 0;
|
||||||
|
char* path = NULL;
|
||||||
|
char* result = NULL;
|
||||||
|
if (request->arguments == NULL || request->arguments->total == 0) {
|
||||||
|
libp2p_logger_error("http_request", "process_name: empty arguments\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
path = (char*) libp2p_utils_vector_get(request->arguments, 0);
|
||||||
|
if (strcmp(request->sub_command, "resolve") == 0) {
|
||||||
|
retVal = ipfs_namesys_resolver_resolve(local_node, path, 1, &result);
|
||||||
|
if (retVal) {
|
||||||
|
*response = (char*) malloc(strlen(result) + 20);
|
||||||
|
sprintf(*response, "{ \"Path\": \"%s\" }", result);
|
||||||
|
}
|
||||||
|
free(result);
|
||||||
|
} else if (strcmp(request->sub_command, "publish") == 0) {
|
||||||
|
retVal = ipfs_namesys_publisher_publish(local_node, path);
|
||||||
|
if (retVal) {
|
||||||
|
*response = (char*) malloc(strlen(local_node->identity->peer->id) + strlen(path) + 30);
|
||||||
|
sprintf(*response, "{ \"Name\": \"%s\"\n \"Value\": \"%s\" }", local_node->identity->peer->id, path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***
|
||||||
|
* Handle processing of the "object" command
|
||||||
|
* @param local_node the context
|
||||||
|
* @param request the incoming request
|
||||||
|
* @param response the response
|
||||||
|
* @returns true(1) on success, false(0) otherwise
|
||||||
|
*/
|
||||||
|
int ipfs_core_http_process_object(struct IpfsNode* local_node, struct HttpRequest* request, char** response) {
|
||||||
|
int retVal = 0;
|
||||||
|
if (strcmp(request->sub_command, "get") == 0) {
|
||||||
|
// do an object_get
|
||||||
|
}
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
/***
|
/***
|
||||||
* Process the parameters passed in from an http request
|
* Process the parameters passed in from an http request
|
||||||
|
* @param local_node the context
|
||||||
* @param request the request
|
* @param request the request
|
||||||
* @param response the response
|
* @param response the response
|
||||||
* @returns true(1) on success, false(0) otherwise.
|
* @returns true(1) on success, false(0) otherwise.
|
||||||
*/
|
*/
|
||||||
int ipfs_core_http_request_process(struct HttpRequest* request, char** response) {
|
int ipfs_core_http_request_process(struct IpfsNode* local_node, struct HttpRequest* request, char** response) {
|
||||||
|
if (request == NULL)
|
||||||
|
return 0;
|
||||||
|
int retVal = 0;
|
||||||
|
|
||||||
|
if (strcmp(request->command, "name") == 0) {
|
||||||
|
retVal = ipfs_core_http_process_name(local_node, request, response);
|
||||||
|
} else if (strcmp(request->command, "object") == 0) {
|
||||||
|
retVal = ipfs_core_http_process_object(local_node, request, response);
|
||||||
|
}
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* just builds the basics of an http api url
|
||||||
|
* @param local_node where to get the ip and port
|
||||||
|
* @returns a string in the form of "http://127.0.0.1:5001/api/v0" (or whatever was in the config file for the API)
|
||||||
|
*/
|
||||||
|
char* ipfs_core_http_request_build_url_start(struct IpfsNode* local_node) {
|
||||||
|
char* host = NULL;
|
||||||
|
char port[10] = "";
|
||||||
|
struct MultiAddress* ma = multiaddress_new_from_string(local_node->repo->config->addresses->api);
|
||||||
|
if (ma == NULL)
|
||||||
|
return NULL;
|
||||||
|
if (!multiaddress_get_ip_address(ma, &host)) {
|
||||||
|
multiaddress_free(ma);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
int portInt = multiaddress_get_ip_port(ma);
|
||||||
|
sprintf(port, "%d", portInt);
|
||||||
|
int len = 18 + strlen(host) + strlen(port);
|
||||||
|
char* retVal = malloc(len);
|
||||||
|
sprintf(retVal, "http://%s:%s/api/v0", host, port);
|
||||||
|
free(host);
|
||||||
|
multiaddress_free(ma);
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***
|
||||||
|
* Adds commands to url
|
||||||
|
* @param request the request
|
||||||
|
* @param url the starting url, and will hold the results (i.e. http://127.0.0.1:5001/api/v0/<command>/<sub_command>
|
||||||
|
* @returns true(1) on success, otherwise false(0)
|
||||||
|
*/
|
||||||
|
int ipfs_core_http_request_add_commands(struct HttpRequest* request, char** url) {
|
||||||
|
// command
|
||||||
|
int addl_length = strlen(request->command) + 2;
|
||||||
|
char* string1 = (char*) malloc(strlen(*url) + addl_length);
|
||||||
|
sprintf(string1, "%s/%s", *url, request->command);
|
||||||
|
free(*url);
|
||||||
|
*url = string1;
|
||||||
|
// sub_command
|
||||||
|
if (request->sub_command != NULL) {
|
||||||
|
addl_length = strlen(request->sub_command) + 2;
|
||||||
|
string1 = (char*) malloc(strlen(*url) + addl_length);
|
||||||
|
sprintf(string1, "%s/%s", *url, request->sub_command);
|
||||||
|
free(*url);
|
||||||
|
*url = string1;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Do an HTTP Get to the local API
|
||||||
|
* @param local_node the context
|
||||||
|
* @param request the request
|
||||||
|
* @param result the results
|
||||||
|
* @returns true(1) on success, false(0) on error
|
||||||
|
*/
|
||||||
|
int ipfs_core_http_request_get(struct IpfsNode* local_node, struct HttpRequest* request, char** result) {
|
||||||
|
if (request == NULL || request->command == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
char* url = ipfs_core_http_request_build_url_start(local_node);
|
||||||
|
if (url == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (!ipfs_core_http_request_add_commands(request, &url)) {
|
||||||
|
free(url);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int request_length = 10 + strlen(request->command);
|
||||||
|
if (request->sub_command != NULL)
|
||||||
|
request_length += 1 + strlen(request->sub_command);
|
||||||
|
//TODO: continue building out this method
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "ipfs/core/ipfs_node.h"
|
||||||
|
|
||||||
/***
|
/***
|
||||||
* A name/value pair of http parameters
|
* A name/value pair of http parameters
|
||||||
*/
|
*/
|
||||||
|
@ -44,8 +46,18 @@ void ipfs_core_http_param_free(struct HttpParam* param);
|
||||||
|
|
||||||
/***
|
/***
|
||||||
* Process the parameters passed in from an http request
|
* Process the parameters passed in from an http request
|
||||||
|
* @param local_node the context
|
||||||
* @param request the request
|
* @param request the request
|
||||||
* @param response the response
|
* @param response the response
|
||||||
* @returns true(1) on success, false(0) otherwise.
|
* @returns true(1) on success, false(0) otherwise.
|
||||||
*/
|
*/
|
||||||
int ipfs_core_http_request_process(struct HttpRequest* request, char** response);
|
int ipfs_core_http_request_process(struct IpfsNode* local_node, struct HttpRequest* request, char** response);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Do an HTTP Get to the local API
|
||||||
|
* @param local_node the context
|
||||||
|
* @param request the request
|
||||||
|
* @param result the results
|
||||||
|
* @returns true(1) on success, false(0) on error
|
||||||
|
*/
|
||||||
|
int ipfs_core_http_request_get(struct IpfsNode* local_node, struct HttpRequest* request, char** result);
|
||||||
|
|
|
@ -5,13 +5,24 @@
|
||||||
#include "libp2p/utils/logger.h"
|
#include "libp2p/utils/logger.h"
|
||||||
#include "ipfs/core/ipfs_node.h"
|
#include "ipfs/core/ipfs_node.h"
|
||||||
#include "ipfs/cmd/cli.h"
|
#include "ipfs/cmd/cli.h"
|
||||||
|
#include "ipfs/core/http_request.h"
|
||||||
|
|
||||||
/***
|
/***
|
||||||
* Publish IPNS name
|
* Publish IPNS name
|
||||||
*/
|
*/
|
||||||
int ipfs_name_publish(struct IpfsNode* local_node, char* name) {
|
int ipfs_name_publish(struct IpfsNode* local_node, char* name) {
|
||||||
// call api
|
// call api.
|
||||||
|
char* response = NULL;
|
||||||
|
struct HttpRequest* request = ipfs_core_http_request_new();
|
||||||
|
if (request == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
|
request->command = "name";
|
||||||
|
request->sub_command = "publish";
|
||||||
|
int retVal = ipfs_core_http_request_get(local_node, request, &response);
|
||||||
|
if (response != NULL)
|
||||||
|
free(response);
|
||||||
|
ipfs_core_http_request_free(request);
|
||||||
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ipfs_name_resolve(struct IpfsNode* local_node, char* name) {
|
int ipfs_name_resolve(struct IpfsNode* local_node, char* name) {
|
||||||
|
|
Loading…
Reference in a new issue