Changeset 4d4f656 in mainline


Ignore:
Timestamp:
2013-09-26T20:50:52Z (11 years ago)
Author:
Martin Sucha <sucha14@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
408424e
Parents:
b623b68
Message:

libhttp: Add higher-level API for working with headers

Location:
uspace
Files:
1 added
5 edited

Legend:

Unmodified
Added
Removed
  • uspace/app/download/main.c

    rb623b68 r4d4f656  
    135135        }
    136136       
    137         http_header_t *header_host = http_header_create("Host", uri->host);
    138         if (header_host == NULL) {
    139                 fprintf(stderr, "Failed creating Host header\n");
    140                 uri_destroy(uri);
    141                 return 3;
    142         }
    143         list_append(&header_host->link, &req->headers);
    144        
    145         http_header_t *header_ua = http_header_create("User-Agent", USER_AGENT);
    146         if (header_ua == NULL) {
    147                 fprintf(stderr, "Failed creating User-Agent header\n");
    148                 uri_destroy(uri);
    149                 return 3;
    150         }
    151         list_append(&header_ua->link, &req->headers);
     137        int rc = http_headers_append(&req->headers, "Host", uri->host);
     138        if (rc != EOK) {
     139                fprintf(stderr, "Failed setting Host header: %s\n", str_error(rc));
     140                uri_destroy(uri);
     141                return rc;
     142        }
     143       
     144        rc = http_headers_append(&req->headers, "User-Agent", USER_AGENT);
     145        if (rc != EOK) {
     146                fprintf(stderr, "Failed creating User-Agent header: %s\n", str_error(rc));
     147                uri_destroy(uri);
     148                return rc;
     149        }
    152150       
    153151        http_t *http = http_create(uri->host, port);
     
    158156        }
    159157       
    160         int rc = http_connect(http);
     158        rc = http_connect(http);
    161159        if (rc != EOK) {
    162160                fprintf(stderr, "Failed connecting: %s\n", str_error(rc));
  • uspace/lib/http/include/http/http.h

    rb623b68 r4d4f656  
    6767
    6868typedef struct {
     69        list_t list;
     70} http_headers_t;
     71
     72typedef struct {
    6973        char *method;
    7074        char *path;
    71         list_t headers;
     75        http_headers_t headers;
    7276} http_request_t;
    7377
     
    7680        uint16_t status;
    7781        char *message;
    78         list_t headers;
     82        http_headers_t headers;
    7983} http_response_t;
    8084
     
    8892extern int http_header_receive(receive_buffer_t *, http_header_t *);
    8993extern void http_header_normalize_value(char *);
     94extern bool http_header_name_match(const char *, const char *);
    9095ssize_t http_header_encode(http_header_t *, char *, size_t);
    9196extern void http_header_destroy(http_header_t *);
     97
     98extern void http_headers_init(http_headers_t *);
     99extern int http_headers_find_single(http_headers_t *, const char *,
     100    http_header_t **);
     101extern int http_headers_append(http_headers_t *, const char *, const char *);
     102extern int http_headers_set(http_headers_t *, const char *, const char *);
     103extern int http_headers_get(http_headers_t *, const char *, char **);
     104extern int http_headers_receive(receive_buffer_t *, http_headers_t *);
     105extern void http_headers_clear(http_headers_t *);
     106
     107#define http_headers_foreach(headers, iter) \
     108    list_foreach((headers).list, link, http_header_t, (iter))
     109
     110static inline void http_headers_remove(http_headers_t *headers,
     111    http_header_t *header)
     112{
     113        list_remove(&header->link);
     114}
     115
     116static inline void http_headers_append_header(http_headers_t *headers,
     117    http_header_t *header)
     118{
     119        list_append(&header->link, &headers->list);
     120}
    92121
    93122extern http_request_t *http_request_create(const char *, const char *);
  • uspace/lib/http/src/headers.c

    rb623b68 r4d4f656  
    4141#include <http/http.h>
    4242#include <http/ctype.h>
     43#include <http/errno.h>
    4344
    4445#define HTTP_HEADER_LINE "%s: %s\r\n"
     
    204205        int rc = http_header_receive_name(rb, &name);
    205206        if (rc != EOK) {
    206                 printf("Failed receiving header name\n");
    207207                return rc;
    208208        }
     
    247247}
    248248
     249/** Test if two header names are equivalent
     250 *
     251 */
     252bool http_header_name_match(const char *name_a, const char *name_b)
     253{
     254        return stricmp(name_a, name_b) == 0;
     255}
     256
     257void http_headers_init(http_headers_t *headers) {
     258        list_initialize(&headers->list);
     259}
     260
     261int http_headers_find_single(http_headers_t *headers, const char *name,
     262    http_header_t **out_header)
     263{
     264        http_header_t *found = NULL;
     265        http_headers_foreach(*headers, header) {
     266                if (!http_header_name_match(header->name, name))
     267                        continue;
     268               
     269                if (found == NULL) {
     270                        found = header;
     271                }
     272                else {
     273                        return HTTP_EMULTIPLE_HEADERS;
     274                }
     275        }
     276       
     277        if (found == NULL)
     278                return HTTP_EMISSING_HEADER;
     279       
     280        *out_header = found;
     281        return EOK;
     282}
     283
     284int http_headers_append(http_headers_t *headers, const char *name,
     285    const char *value)
     286{
     287        http_header_t *header = http_header_create(name, value);
     288        if (header == NULL)
     289                return ENOMEM;
     290       
     291        http_headers_append_header(headers, header);
     292        return EOK;
     293}
     294
     295int http_headers_set(http_headers_t *headers, const char *name,
     296    const char *value)
     297{
     298        http_header_t *header = NULL;
     299        int rc = http_headers_find_single(headers, name, &header);
     300        if (rc != EOK && rc != HTTP_EMISSING_HEADER)
     301                return rc;
     302       
     303        if (rc == HTTP_EMISSING_HEADER)
     304                return http_headers_append(headers, name, value);
     305       
     306        char *new_value = str_dup(value);
     307        if (new_value == NULL)
     308                return ENOMEM;
     309       
     310        free(header->value);
     311        header->value = new_value;
     312        return EOK;
     313}
     314
     315int http_headers_get(http_headers_t *headers, const char *name, char **value)
     316{
     317        http_header_t *header = NULL;
     318        int rc = http_headers_find_single(headers, name, &header);
     319        if (rc != EOK)
     320                return rc;
     321       
     322        *value = header->value;
     323        return EOK;
     324}
     325
     326int http_headers_receive(receive_buffer_t *rb, http_headers_t *headers)
     327{
     328        int rc = EOK;
     329        unsigned added = 0;
     330       
     331        while (true) {
     332                char c = 0;
     333                rc = recv_char(rb, &c, false);
     334                if (rc != EOK)
     335                        goto error;
     336               
     337                if (c == '\n' || c == '\r')
     338                        break;
     339               
     340                http_header_t *header = malloc(sizeof(http_header_t));
     341                if (header == NULL) {
     342                        rc = ENOMEM;
     343                        goto error;
     344                }
     345                http_header_init(header);
     346               
     347                rc = http_header_receive(rb, header);
     348                if (rc != EOK) {
     349                        free(header);
     350                        goto error;
     351                }
     352               
     353                http_headers_append_header(headers, header);
     354                added++;
     355        }
     356       
     357        return EOK;
     358error:
     359        while (added-- > 0) {
     360                link_t *link = list_last(&headers->list);
     361                http_header_t *header = list_get_instance(link, http_header_t, link);
     362                http_headers_remove(headers, header);
     363                http_header_destroy(header);
     364        }
     365        return rc;
     366}
     367
     368void http_headers_clear(http_headers_t *headers)
     369{
     370        link_t *link = list_first(&headers->list);
     371        while (link != NULL) {
     372                link_t *next = list_next(link, &headers->list);
     373                http_header_t *header = list_get_instance(link, http_header_t, link);
     374                list_remove(link);
     375                http_header_destroy(header);
     376                link = next;
     377        }
     378}
     379
    249380/** @}
    250381 */
  • uspace/lib/http/src/request.c

    rb623b68 r4d4f656  
    6565        }
    6666       
    67         list_initialize(&req->headers);
     67        http_headers_init(&req->headers);
    6868       
    6969        return req;
     
    7474        free(req->method);
    7575        free(req->path);
    76         link_t *link = req->headers.head.next;
    77         while (link != &req->headers.head) {
    78                 link_t *next = link->next;
    79                 http_header_t *header = list_get_instance(link, http_header_t, link);
    80                 http_header_destroy(header);
    81                 link = next;
    82         }
     76        http_headers_clear(&req->headers);
    8377        free(req);
    8478}
     
    10498        size_t size = meth_size;
    10599       
    106         list_foreach(req->headers, link, http_header_t, header) {
     100        http_headers_foreach(req->headers, header) {
    107101                ssize_t header_size = http_header_encode(header, NULL, 0);
    108102                if (header_size < 0)
     
    126120        pos_size -= written;
    127121       
    128         list_foreach(req->headers, link, http_header_t, header) {
     122        http_headers_foreach(req->headers, header) {
    129123                written = http_header_encode(header, pos, pos_size);
    130124                if (written < 0) {
  • uspace/lib/http/src/response.c

    rb623b68 r4d4f656  
    4040
    4141#include <http/http.h>
     42#include <http/errno.h>
    4243
    4344int http_parse_status(const char *line, http_version_t *out_version,
     
    9899                return ENOMEM;
    99100        memset(resp, 0, sizeof(http_response_t));
    100         list_initialize(&resp->headers);
     101        http_headers_init(&resp->headers);
    101102       
    102103        char *line = malloc(http->buffer_size);
     
    115116                goto error;
    116117       
    117         while (true) {
    118                 rc = recv_eol(&http->recv_buffer);
    119                 if (rc < 0)
    120                         goto error;
    121                
    122                 /* Empty line ends header part */
    123                 if (rc > 0)
    124                         break;
    125                
    126                 http_header_t *header = malloc(sizeof(http_header_t));
    127                 if (header == NULL) {
    128                         rc = ENOMEM;
    129                         goto error;
    130                 }
    131                 http_header_init(header);
    132                
    133                 rc = http_header_receive(&http->recv_buffer, header);
    134                 if (rc != EOK) {
    135                         free(header);
    136                         goto error;
    137                 }
    138                
    139                 list_append(&header->link, &resp->headers);
    140         }
     118        rc = http_headers_receive(&http->recv_buffer, &resp->headers);
     119        if (rc != EOK)
     120                goto error;
     121       
     122        rc = recv_eol(&http->recv_buffer);
     123        if (rc == 0)
     124                rc = HTTP_EPARSE;
     125        if (rc < 0)
     126                goto error;
    141127       
    142128        *out_response = resp;
     
    157143{
    158144        free(resp->message);
    159         link_t *link = resp->headers.head.next;
    160         while (link != &resp->headers.head) {
    161                 link_t *next = link->next;
    162                 http_header_t *header = list_get_instance(link, http_header_t, link);
    163                 http_header_destroy(header);
    164                 link = next;
    165         }
     145        http_headers_clear(&resp->headers);
    166146        free(resp);
    167147}
Note: See TracChangeset for help on using the changeset viewer.