Work on requests

This commit adds tests for a request and the implementation.

The first line of a request should now be decoded correctly
master
Jonathan Hodgson 3 years ago
parent 66d4702297
commit 0e2b9dae2b
  1. 57
      src/request.c
  2. 12
      src/request.h
  3. 2
      tests/all.test.c
  4. 162
      tests/request.test.c

@ -47,23 +47,72 @@ Request* newRequest(){
return request;
}
void requestFirstLine( Request *req, char line[] ){
char method[20] = {'\0'}; //Get, post, etc.
char *url = malloc(sizeof(char) *2048); // This may contain the method, the path, the domain and so on
memset(url, '\0', sizeof(char) * 2048);
char *currentPos;
float version = 0;
char protocol[6] = {'\0'};
char host[254] = {'\0'};
//https://stackoverflow.com/questions/417142/what-is-the-maximum-length-of-a-url-in-different-browsers
char path[2000] = {'\0'};
sscanf( line, "%20s %2048s HTTP/%f", method, url, &version );
req->method = method;
req->version = version;
//We've pulled out the easy bits. Now to go through the url and pull out what we need
currentPos = url;
sscanf( currentPos, "%5[^:/]", protocol );
if ( strlen( protocol ) > 0 ){
currentPos = currentPos + strlen(protocol) + 3;
}
sscanf( currentPos, "%253[^:/]", host );
if ( strlen( host ) > 0 ){
currentPos = currentPos + strlen(host);
}
sscanf( currentPos, "%2000[^? ]", path );
if ( strlen( path ) > 0 ){
currentPos = currentPos + strlen(path);
}
req->protocol = malloc(sizeof(char) * strlen(protocol));
strcpy(req->protocol, protocol);
req->host = malloc(sizeof(char) * strlen(host));
strcpy(req->host, host);
req->path = malloc(sizeof(char) * strlen(path));
strcpy(req->path, path);
//The query string is anything left
req->queryString = malloc(sizeof(char) * strlen(currentPos));
strcpy(req->queryString, currentPos);
free(url);
}
Request* newRequestFromSocket(int socket){
Request *req = newRequest();
int valread;
char line[1024] = {0};
valread = fdReadLine( socket , line, 1024);
// The first line will give us some important information
//valread = fdReadLine( socket, line, 1024);
char hello[] = "this is a test";
// The first line will give us some important information
printf("HERE\nLine is %s\n", line);
//a length of 2 will indicate an empty line which will split the headers
//from the body (if there is a body)
while ( valread > 2 ){
printf("%s",line );
valread = fdReadLine( socket , line, 1024);
//valread = fdReadLine( socket , line, 1024);
}
send(socket , hello , strlen(hello) , 0 );
send(socket , "this is a test" , 15 , 0 );
printf("Hello message sent\n");
return req;
}

@ -7,8 +7,6 @@
#include "readline.h"
#include <netinet/in.h>
typedef enum {HTTP,HTTPS} HTTPProtocol;
typedef enum {GET, HEAD, POST, PUT, DELETE, CONNECT, OPTIONS, TRACE, PATCH} HTTPMethod;
/*
* A struct reperesenting an http header
@ -33,9 +31,9 @@ struct HeaderList {
*/
typedef struct {
// Common versions are: 0.9, 1.0, 1.1, 2.0
double version;
HTTPMethod method;
HTTPProtocol protocol;
float version;
char *method;
char *protocol;
char *host;
char *path;
HeaderList *headers;
@ -45,8 +43,10 @@ typedef struct {
Header* newHeader();
Request* newRequest();
void requestFirstLine( Request *req, char line[] );
Request* newRequestFromSocket(int socket);
void* addHeader(Request *req);
void* addHeader(Request *req, char line[]);
void* interpretLine1(Request *req, char line[]);

@ -3,6 +3,7 @@
#include "munit/munit.h"
#include "config.test.c"
#include "request.test.c"
#include <string.h>
#include <stdio.h>
@ -13,6 +14,7 @@ int main (int argc, char* argv[]) {
MunitSuite all_suites[] = {
config_test_suite,
request_test_suite,
{ NULL, NULL, NULL, 0, MUNIT_SUITE_OPTION_NONE }
};

@ -0,0 +1,162 @@
#include "munit/munit.h"
#include "../src/request.c"
typedef struct {
char *fullLine;
char *method;
char *host;
char *protocol;
double version;
char *path;
char *queryString;
} firstLine;
static firstLine line1Examples[] = {
//Full Line, Method Host Protocol Version Path
{ "GET /search?q=test HTTP/2", "GET", "", "", 2, "/search", "?q=test"},
{ "POST http://example.com/test HTTP/1.1", "POST", "example.com", "http", 1.1, "/test", "" },
{ "POST https://example.com/test/test2/test3 HTTP/1.1", "POST", "example.com", "https", 1.1, "/test/test2/test3", ""},
{ NULL, NULL, NULL, NULL, 0, NULL, NULL }
};
MunitResult testFirstLineProtocols(const MunitParameter params[],
void* user_data_or_fixture){
Request *req;
for ( firstLine *line = line1Examples; line->fullLine != NULL; line++ ){
req = newRequest();
requestFirstLine( req, line->fullLine );
munit_assert_string_equal( req->protocol, line->protocol );
free( req );
}
return MUNIT_OK;
}
MunitResult testFirstLineMethod(const MunitParameter params[],
void* user_data_or_fixture){
Request *req;
for ( firstLine *line = line1Examples; line->fullLine != NULL; line++ ){
req = newRequest();
requestFirstLine( req, line->fullLine );
munit_assert_string_equal( req->method, line->method );
free( req );
}
return MUNIT_OK;
}
MunitResult testFirstLineHosts(const MunitParameter params[],
void* user_data_or_fixture){
Request *req;
for ( firstLine *line = line1Examples; line->fullLine != NULL; line++ ){
req = newRequest();
requestFirstLine( req, line->fullLine );
munit_assert_string_equal( req->host, line->host );
free( req );
}
return MUNIT_OK;
}
MunitResult testFirstLinePaths(const MunitParameter params[],
void* user_data_or_fixture){
Request *req;
for ( firstLine *line = line1Examples; line->fullLine != NULL; line++ ){
req = newRequest();
requestFirstLine( req, line->fullLine );
munit_assert_string_equal( req->path, line->path );
free( req );
}
return MUNIT_OK;
}
MunitResult testFirstLineVersions(const MunitParameter params[],
void* user_data_or_fixture){
Request *req;
for ( firstLine *line = line1Examples; line->fullLine != NULL; line++ ){
req = newRequest();
requestFirstLine( req, line->fullLine );
munit_assert_float( req->version, ==, line->version );
free( req );
}
return MUNIT_OK;
}
MunitResult testFirstLineQueryString(const MunitParameter params[],
void* user_data_or_fixture){
Request *req;
for ( firstLine *line = line1Examples; line->fullLine != NULL; line++ ){
req = newRequest();
requestFirstLine( req, line->fullLine );
munit_assert_string_equal( req->queryString, line->queryString );
free( req );
}
return MUNIT_OK;
}
static MunitTest request_tests[] = {
{
"/line1/versions", /* name */
testFirstLineVersions, /* test */
NULL, /* setup */
NULL, /* tear_down */
MUNIT_TEST_OPTION_NONE, /* options */
NULL /* parameters */
}, {
"/line1/methods", /* name */
testFirstLineMethod, /* test */
NULL, /* setup */
NULL, /* tear_down */
MUNIT_TEST_OPTION_NONE, /* options */
NULL /* parameters */
},{
"/line1/protocols", /* name */
testFirstLineProtocols, /* test */
NULL, /* setup */
NULL, /* tear_down */
MUNIT_TEST_OPTION_NONE, /* options */
NULL /* parameters */
},{
"/line1/hosts", /* name */
testFirstLineHosts, /* test */
NULL, /* setup */
NULL, /* tear_down */
MUNIT_TEST_OPTION_NONE, /* options */
NULL /* parameters */
},{
"/line1/paths", /* name */
testFirstLinePaths, /* test */
NULL, /* setup */
NULL, /* tear_down */
MUNIT_TEST_OPTION_NONE, /* options */
NULL /* parameters */
},{
"/line1/queryStrings", /* name */
testFirstLineQueryString, /* test */
NULL, /* setup */
NULL, /* tear_down */
MUNIT_TEST_OPTION_NONE, /* options */
NULL /* parameters */
},
/* Mark the end of the array with an entry where the test
* function is NULL */
{ NULL, NULL, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL }
};
MunitSuite request_test_suite = {
"/request", /* name */
request_tests, /* tests */
NULL, /* suites */
1, /* iterations */
MUNIT_SUITE_OPTION_NONE /* options */
};
#ifndef MAINTEST
#define MAINTEST
int main (int argc, char* argv[]) {
return munit_suite_main(&request_test_suite, NULL, argc, argv);
}
#endif /* ifndef MAINTEST */
Loading…
Cancel
Save