Add the capability to write custom HTTP headers
Patch by Josh Allmann, joshua dot allmann at gmail Originally committed as revision 23526 to svn://svn.ffmpeg.org/ffmpeg/trunk
This commit is contained in:
parent
0f3254b83d
commit
6964d510e8
@ -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 {
|
|||||||
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)
|
|||||||
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,
|
|||||||
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)
|
||||||
|
42
libavformat/http.h
Normal file
42
libavformat/http.h
Normal file
@ -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 */
|
Loading…
x
Reference in New Issue
Block a user