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;
|
||||
};
|
||||
|
||||
/***
|
||||
* 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.
|
||||
* @param ptr an ApiConnectionParam
|
||||
|
@ -420,11 +434,10 @@ void *api_connection_thread (void *ptr)
|
|||
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) {
|
||||
char *path;
|
||||
unsigned char *obj;
|
||||
size_t size;
|
||||
|
||||
if (strcmp (req.buf + req.path, "/")==0 ||
|
||||
strcmp (req.buf + req.path, "/webui") ||
|
||||
|
@ -441,23 +454,13 @@ void *api_connection_thread (void *ptr)
|
|||
} else {
|
||||
write_cstr (s, HTTP_500);
|
||||
}
|
||||
further_processing_necessary = 0;
|
||||
} else {
|
||||
//TODO: build http_request here
|
||||
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, ' '));
|
||||
}
|
||||
// move out of the if to do further processing
|
||||
}
|
||||
// end of GET
|
||||
} else if (strcmp(buf + req.method, "POST")==0) {
|
||||
// TODO: Handle gzip/json POST requests.
|
||||
// TODO: build http_request here
|
||||
|
||||
p = header_value_cmp(&req, "Content-Type:", "multipart/form-data;");
|
||||
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) {
|
||||
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"
|
||||
"http_ver = '%s'\n"
|
||||
"header {\n%s\n}\n"
|
||||
"body_size = %d\n",
|
||||
req.buf+req.method, req.buf+req.path, req.buf+req.http_ver,
|
||||
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;
|
||||
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");
|
||||
// TODO: Handle this condition
|
||||
}
|
||||
ipfs_core_http_request_free(http_request);
|
||||
|
||||
// now send the results
|
||||
snprintf(resp, sizeof(resp), "%s 200 OK\r\n" \
|
||||
"Content-Type: application/json\r\n"
|
||||
"Server: c-ipfs/0.0.0-dev\r\n"
|
||||
"X-Chunked-Output: 1\r\n"
|
||||
"Connection: close\r\n"
|
||||
"Transfer-Encoding: chunked\r\n\r\n%s", req.buf + req.http_ver, response_text);
|
||||
if (response_text != NULL)
|
||||
free(response_text);
|
||||
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 {
|
||||
// Unexpected???
|
||||
libp2p_logger_error("api", "fail unexpected '%s'.\n", req.buf + req.method);
|
||||
write_cstr (s, HTTP_500);
|
||||
// uh oh... something went wrong converting to the HttpRequest struct
|
||||
libp2p_logger_error("api", "Unable to build HttpRequest struct.\n");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
libp2p_logger_error("api", "fail looking for body.\n");
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "libp2p/utils/vector.h"
|
||||
#include "libp2p/utils/logger.h"
|
||||
#include "ipfs/core/http_request.h"
|
||||
#include "ipfs/namesys/resolver.h"
|
||||
#include "ipfs/namesys/publisher.h"
|
||||
|
||||
/**
|
||||
* Handles HttpRequest and HttpParam
|
||||
|
@ -27,10 +31,10 @@ struct HttpRequest* ipfs_core_http_request_new() {
|
|||
*/
|
||||
void ipfs_core_http_request_free(struct HttpRequest* request) {
|
||||
if (request != NULL) {
|
||||
if (request->command != NULL)
|
||||
free(request->command);
|
||||
if (request->sub_command != NULL)
|
||||
free(request->sub_command);
|
||||
//if (request->command != NULL)
|
||||
// free(request->command);
|
||||
//if (request->sub_command != NULL)
|
||||
// free(request->sub_command);
|
||||
if (request->params != NULL) {
|
||||
for(int i = 0; i < request->params->total; 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
|
||||
* @param local_node the context
|
||||
* @param request the request
|
||||
* @param response the response
|
||||
* @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;
|
||||
}
|
||||
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
|
||||
|
||||
#include "ipfs/core/ipfs_node.h"
|
||||
|
||||
/***
|
||||
* 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
|
||||
* @param local_node the context
|
||||
* @param request the request
|
||||
* @param response the response
|
||||
* @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 "ipfs/core/ipfs_node.h"
|
||||
#include "ipfs/cmd/cli.h"
|
||||
#include "ipfs/core/http_request.h"
|
||||
|
||||
/***
|
||||
* Publish IPNS 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;
|
||||
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) {
|
||||
|
|
Loading…
Reference in a new issue