Filling in more of http_request

This commit is contained in:
jmjatlanta 2017-09-21 17:10:41 -05:00
parent b133a703cc
commit c54cf989c0
4 changed files with 221 additions and 44 deletions

View file

@ -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");

View file

@ -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;
}
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; return 0;
} }

View file

@ -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);

View file

@ -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) {