# HG changeset patch # User mstorsjo # Date 1275992776 0 # Node ID a5eaf91edd4a05a2b18ed78311d4194df0c41b2a # Parent 447fe3440991f864be67f341bde2662e0927a959 Add the capability to write custom HTTP headers Patch by Josh Allmann, joshua dot allmann at gmail diff -r 447fe3440991 -r a5eaf91edd4a http.c --- a/http.c Tue Jun 08 10:04:39 2010 +0000 +++ b/http.c Tue Jun 08 10:26:16 2010 +0000 @@ -25,6 +25,7 @@ #include #include "internal.h" #include "network.h" +#include "http.h" #include "os_support.h" #include "httpauth.h" @@ -46,12 +47,23 @@ char location[URL_SIZE]; HTTPAuthState auth_state; int init; + unsigned char headers[BUFFER_SIZE]; } HTTPContext; static int http_connect(URLContext *h, const char *path, const char *hoststr, const char *auth, int *new_location); static int http_write(URLContext *h, const uint8_t *buf, int size); +void ff_http_set_headers(URLContext *h, const char *headers) +{ + HTTPContext *s = h->priv_data; + int len = strlen(headers); + + if (len && strcmp("\r\n", headers + len - 2)) + av_log(NULL, AV_LOG_ERROR, "No trailing CRLF found in HTTP header.\n"); + + av_strlcpy(s->headers, headers, sizeof(s->headers)); +} /* return non zero if error */ static int http_open_cnx(URLContext *h) @@ -137,6 +149,7 @@ s->chunksize = -1; s->off = 0; s->init = 0; + *s->headers = '\0'; memset(&s->auth_state, 0, sizeof(s->auth_state)); av_strlcpy(s->location, uri, URL_SIZE); @@ -245,37 +258,60 @@ return 1; } +static inline int has_header(const char *str, const char *header) +{ + /* header + 2 to skip over CRLF prefix. (make sure you have one!) */ + return av_stristart(str, header + 2, NULL) || av_stristr(str, header); +} + static int http_connect(URLContext *h, const char *path, const char *hoststr, const char *auth, int *new_location) { HTTPContext *s = h->priv_data; int post, err; char line[1024]; + char headers[1024]; char *authstr = NULL; int64_t off = s->off; + int len = 0; /* send http header */ post = h->flags & URL_WRONLY; authstr = ff_http_auth_create_response(&s->auth_state, auth, path, post ? "POST" : "GET"); + + /* set default headers if needed */ + if (!has_header(s->headers, "\r\nUser-Agent: ")) + len += av_strlcatf(headers + len, sizeof(headers) - len, + "User-Agent: %s\r\n", LIBAVFORMAT_IDENT); + if (!has_header(s->headers, "\r\nAccept: ")) + len += av_strlcpy(headers + len, "Accept: */*\r\n", + sizeof(headers) - len); + if (!has_header(s->headers, "\r\nRange: ")) + len += av_strlcatf(headers + len, sizeof(headers) - len, + "Range: bytes=%"PRId64"\r\n", s->off); + if (!has_header(s->headers, "\r\nConnection: ")) + len += av_strlcpy(headers + len, "Connection: close\r\n", + sizeof(headers)-len); + if (!has_header(s->headers, "\r\nHost: ")) + len += av_strlcatf(headers + len, sizeof(headers) - len, + "Host: %s\r\n", hoststr); + + /* now add in custom headers */ + av_strlcpy(headers+len, s->headers, sizeof(headers)-len); + snprintf(s->buffer, sizeof(s->buffer), "%s %s HTTP/1.1\r\n" - "User-Agent: %s\r\n" - "Accept: */*\r\n" - "Range: bytes=%"PRId64"-\r\n" - "Host: %s\r\n" "%s" - "Connection: close\r\n" + "%s" "%s" "\r\n", post ? "POST" : "GET", path, - LIBAVFORMAT_IDENT, - s->off, - hoststr, - authstr ? authstr : "", - post ? "Transfer-Encoding: chunked\r\n" : ""); + post ? "Transfer-Encoding: chunked\r\n" : "", + headers, + authstr ? authstr : ""); av_freep(&authstr); if (http_write(h, s->buffer, strlen(s->buffer)) < 0) diff -r 447fe3440991 -r a5eaf91edd4a http.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/http.h Tue Jun 08 10:26:16 2010 +0000 @@ -0,0 +1,42 @@ +/* + * HTTP definitions + * Copyright (c) 2010 Josh Allmann + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +#ifndef AVFORMAT_HTTP_H +#define AVFORMAT_HTTP_H + +/** + * Sets custom HTTP headers. + * A trailing CRLF ("\r\n") is required for custom headers. + * Passing in an empty header string ("\0") will reset to defaults. + * + * The following headers can be overriden by custom values, + * otherwise they will be set to their defaults. + * -User-Agent + * -Accept + * -Range + * -Host + * -Connection + * + * @param h URL context for this HTTP connection + * @param headers the custom headers to set + */ +void ff_http_set_headers(URLContext *h, const char *headers); + +#endif /* AVFORMAT_HTTP_H */