various fixes for Spring 2021

- support for 206 return code
- fixes to sendfile
- add URL variable to testloginapi.sh
This commit is contained in:
Godmar Back 2021-04-14 00:31:37 -04:00
parent 07658f3b90
commit 7ba2670512
5 changed files with 32 additions and 11 deletions

View File

@ -108,6 +108,9 @@ read_more(struct bufio *self)
/* Given an offset into the buffer, return a char *.
* This pointer will be valid only until the next call
* to any of the bufio_read* function.
*
* The returned pointer is not guaranteed to point to a
* zero-terminated string.
*/
char *
bufio_offset2ptr(struct bufio *self, size_t offset)
@ -194,7 +197,7 @@ bufio_read(struct bufio *self, size_t count, size_t *buf_offset)
* See sendfile(2) for return value.
*/
ssize_t
bufio_sendfile(struct bufio *self, int fd, off_t *off, int filesize)
bufio_sendfile(struct bufio *self, int fd, off_t *off, size_t filesize)
{
return sendfile(self->socket, fd, off, filesize);
}

View File

@ -13,7 +13,7 @@ ssize_t bufio_readline(struct bufio *self, size_t *line_offset);
ssize_t bufio_read(struct bufio *self, size_t count, size_t *buf_offset);
char * bufio_offset2ptr(struct bufio *self, size_t offset);
size_t bufio_ptr2offset(struct bufio *self, char *ptr);
ssize_t bufio_sendfile(struct bufio *self, int fd, off_t *off, int filesize);
ssize_t bufio_sendfile(struct bufio *self, int fd, off_t *off, size_t filesize);
ssize_t bufio_sendbuffer(struct bufio *self, buffer_t *response);
#endif /* _BUFIO_H */

View File

@ -28,6 +28,7 @@
// Need macros here because of the sizeof
#define CRLF "\r\n"
#define CR "\r"
#define STARTS_WITH(field_name, header) \
(!strncasecmp(field_name, header, sizeof(header) - 1))
@ -41,6 +42,7 @@ http_parse_request(struct http_transaction *ta)
return false;
char *request = bufio_offset2ptr(ta->client->bufio, req_offset);
request[len-2] = '\0'; // replace LF with 0 to ensure zero-termination
char *endptr;
char *method = strtok_r(request, " ", &endptr);
if (method == NULL)
@ -59,10 +61,11 @@ http_parse_request(struct http_transaction *ta)
ta->req_path = bufio_ptr2offset(ta->client->bufio, req_path);
char *http_version = strtok_r(NULL, CRLF, &endptr);
char *http_version = strtok_r(NULL, CR, &endptr);
if (http_version == NULL) // would be HTTP 0.9
return false;
// record client's HTTP version in request
if (!strcmp(http_version, "HTTP/1.1"))
ta->req_version = HTTP_1_1;
else if (!strcmp(http_version, "HTTP/1.0"))
@ -97,7 +100,7 @@ http_process_headers(struct http_transaction *ta)
char *field_name = strtok_r(header, ":", &endptr);
char *field_value = strtok_r(NULL, " \t", &endptr); // skip leading & trailing OWS
if (field_name == NULL)
if (field_name == NULL || field_value == NULL)
return false;
// printf("Header: %s: %s\n", field_name, field_value);
@ -147,6 +150,9 @@ start_response(struct http_transaction * ta, buffer_t *res)
case HTTP_OK:
buffer_appends(res, "200 OK");
break;
case HTTP_PARTIAL_CONTENT:
buffer_appends(res, "206 Partial Content");
break;
case HTTP_BAD_REQUEST:
buffer_appends(res, "400 Bad Request");
break;
@ -295,20 +301,26 @@ handle_static_asset(struct http_transaction *ta, char *basedir)
}
ta->resp_status = HTTP_OK;
add_content_length(&ta->resp_headers, st.st_size);
http_add_header(&ta->resp_headers, "Content-Type", "%s", guess_mime_type(fname));
off_t from = 0, to = st.st_size - 1;
off_t content_length = to + 1 - from;
add_content_length(&ta->resp_headers, content_length);
bool success = send_response_header(ta);
if (!success)
goto out;
success = bufio_sendfile(ta->client->bufio, filefd, NULL, st.st_size) == st.st_size;
// sendfile may send fewer bytes than requested, hence the loop
while (success && from <= to)
success = bufio_sendfile(ta->client->bufio, filefd, &from, to + 1 - from) > 0;
out:
close(filefd);
return success;
}
static int
static bool
handle_api(struct http_transaction *ta)
{
return send_error(ta, HTTP_NOT_FOUND, "API not implemented");

View File

@ -20,6 +20,7 @@ enum http_version {
enum http_response_status {
HTTP_OK = 200,
HTTP_PARTIAL_CONTENT = 206,
HTTP_BAD_REQUEST = 400,
HTTP_PERMISSION_DENIED = 403,
HTTP_NOT_FOUND = 404,

View File

@ -2,8 +2,13 @@
# change this as per instruction to avoid conflicts.
PORT=10000
# to test against a working implementation (and see the intended responses)
# change this URL=http://theta.cs.vt.edu:3000/
URL=http://localhost:${PORT}
COOKIEJAR=cookies.txt
# clear cookies
/bin/rm ${COOKIEJAR}
@ -12,20 +17,20 @@ curl -v -H "Content-Type: application/json" \
-c ${COOKIEJAR} \
-X POST \
-d '{"username":"user0","password":"thepassword"}' \
http://localhost:${PORT}/api/login
${URL}/api/login
# this should succeed if the password is correct
curl -v \
-b ${COOKIEJAR} \
http://localhost:${PORT}/api/login
${URL}/api/login
# create a 'private' folder first.
# this should fail since credentials were not presented
curl -v \
http://localhost:${PORT}/private/secret.txt
${URL}/private/secret.txt
# this should succeed since credentials were presented
curl -v \
-b ${COOKIEJAR} \
http://localhost:${PORT}/private/secret.txt
${URl}/private/secret.txt