Commit e26b576e authored by mstorsjo's avatar mstorsjo

Add the capability to write custom HTTP headers

Patch by Josh Allmann, joshua dot allmann at gmail


git-svn-id: file:///var/local/repositories/ffmpeg/trunk@23526 9553f0bf-9b14-0410-a0b8-cfaf0461ba5b
parent 5d0414ab
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include <strings.h> #include <strings.h>
#include "internal.h" #include "internal.h"
#include "network.h" #include "network.h"
#include "http.h"
#include "os_support.h" #include "os_support.h"
#include "httpauth.h" #include "httpauth.h"
...@@ -46,12 +47,23 @@ typedef struct { ...@@ -46,12 +47,23 @@ typedef struct {
char location[URL_SIZE]; char location[URL_SIZE];
HTTPAuthState auth_state; HTTPAuthState auth_state;
int init; int init;
unsigned char headers[BUFFER_SIZE];
} HTTPContext; } HTTPContext;
static int http_connect(URLContext *h, const char *path, const char *hoststr, static int http_connect(URLContext *h, const char *path, const char *hoststr,
const char *auth, int *new_location); const char *auth, int *new_location);
static int http_write(URLContext *h, const uint8_t *buf, int size); 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 */ /* return non zero if error */
static int http_open_cnx(URLContext *h) static int http_open_cnx(URLContext *h)
...@@ -137,6 +149,7 @@ static int http_open(URLContext *h, const char *uri, int flags) ...@@ -137,6 +149,7 @@ static int http_open(URLContext *h, const char *uri, int flags)
s->chunksize = -1; s->chunksize = -1;
s->off = 0; s->off = 0;
s->init = 0; s->init = 0;
*s->headers = '\0';
memset(&s->auth_state, 0, sizeof(s->auth_state)); memset(&s->auth_state, 0, sizeof(s->auth_state));
av_strlcpy(s->location, uri, URL_SIZE); av_strlcpy(s->location, uri, URL_SIZE);
...@@ -245,37 +258,60 @@ static int process_line(URLContext *h, char *line, int line_count, ...@@ -245,37 +258,60 @@ static int process_line(URLContext *h, char *line, int line_count,
return 1; 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, static int http_connect(URLContext *h, const char *path, const char *hoststr,
const char *auth, int *new_location) const char *auth, int *new_location)
{ {
HTTPContext *s = h->priv_data; HTTPContext *s = h->priv_data;
int post, err; int post, err;
char line[1024]; char line[1024];
char headers[1024];
char *authstr = NULL; char *authstr = NULL;
int64_t off = s->off; int64_t off = s->off;
int len = 0;
/* send http header */ /* send http header */
post = h->flags & URL_WRONLY; post = h->flags & URL_WRONLY;
authstr = ff_http_auth_create_response(&s->auth_state, auth, path, authstr = ff_http_auth_create_response(&s->auth_state, auth, path,
post ? "POST" : "GET"); 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), snprintf(s->buffer, sizeof(s->buffer),
"%s %s HTTP/1.1\r\n" "%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" "%s"
"Connection: close\r\n" "%s"
"%s" "%s"
"\r\n", "\r\n",
post ? "POST" : "GET", post ? "POST" : "GET",
path, path,
LIBAVFORMAT_IDENT, post ? "Transfer-Encoding: chunked\r\n" : "",
s->off, headers,
hoststr, authstr ? authstr : "");
authstr ? authstr : "",
post ? "Transfer-Encoding: chunked\r\n" : "");
av_freep(&authstr); av_freep(&authstr);
if (http_write(h, s->buffer, strlen(s->buffer)) < 0) if (http_write(h, s->buffer, strlen(s->buffer)) < 0)
......
/*
* 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 */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment