Bug 31952

Summary: mod_proxy and RealPlayer: audio content streaming does not work
Product: Apache httpd-2 Reporter: Ilya Dogadaev <ilya_dogadaev>
Component: mod_proxyAssignee: Apache HTTPD Bugs Mailing List <bugs>
Severity: enhancement CC: ahayes
Priority: P3 Keywords: MassUpdate, PatchAvailable
Version: 2.0.54   
Target Milestone: ---   
Hardware: All   
OS: All   
Attachments: mod_proxy_http (from 2.0.52) with my fixes added

Description Ilya Dogadaev 2004-10-29 08:57:26 UTC
1. Install and configure Apache to act as HTTP proxy
2. Install RealPlayer 10.0
3. Configure RealPlayer to use HTTP proxy installed in 1 (Menu->Tools-
4. Try listening to the e.g. following sites:
5. Content is not delivered to RealPlayer, radio doesn't work

First site is using ICY-over-HTTP protocol and replies "ICY 200 OK" to apache 
that mod_proxy_http.c fails to understand. The fix follows:
<!--ap_proxy_http_process_response function
if (apr_date_checkmask(buffer, "HTTP/#.# ###*")) {
  //no changes here
else if (apr_date_checkmask(buffer, "ICY ###*")) {//FIX FIX FIX
  /*this fixes the problem for RP 10.0*/
  /*RP 8.0 still doesn't work because it expects ICY/1.0 reply*/
  /*instead of HTTP/1.x apache provides it with*/
  int ind = 7;
  ap_log_error(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r->server,
    "proxy: tid=%d ICY response!!!", myGetCurrentThreadId());
  keepchar = buffer[ind];
  buffer[ind] = '\0';
  r->status = atoi(&buffer[ind-3]);
  buffer[ind] = keepchar;
  r->status_line = apr_pstrdup(p, &buffer[ind-3]);
  r->headers_out = ap_proxy_read_headers(r, rp, buffer,
     sizeof(buffer), origin);
  backasswards = 1;
  r->status = 200;
  r->status_line = "200 OK";


Second site is using RTSP-over-HTTP protocol.
The changes required to mod_proxy_http to support this protocol are minimal and 
include the following:
1. POST requests
http://developer.apple.com/quicktime/icefloe/dispatch028.html says that POST 
requests specify bogus Content-Length: 32767 while in fact such tunneled RTSP-
over-HTTP POSTS request are not going to end at all, client/proxy should be 
prepared that connection will be just closed after a while, and it MUST NOT 
expect any response from remote server, as this is one-way communication 
channel. So ap_proxy_http_process_response() should not be called for RTSP 
/* send request headers */
const char * ct = apr_table_get(r->headers_in, "Content-Type");
if (r->method_number == M_POST)	{
  if ((ct != NULL) && (stricmp(ct, "application/x-pncmd") == 0)) {
    r->connection->keepalive = AP_CONN_CLOSE;
    /*this is RTSP POST request, remember that!*/
    /*Q: is there any better/more reliable way to*/
    apr_table_set(r->notes, "mod_proxy_http::rtsp_post_request", "1");
and then in the beginning of ap_proxy_http_process_response:
const char * rtsp_post = apr_table_get(
           r->notes, "mod_proxy_http::rtsp_post_request");
if ((rtsp_post != NULL) && ((*rtsp_post) == '1'))
  ap_log_error(APLOG_MARK, APLOG_INFO, APR_SUCCESS, r->server,
     "proxy: rtsp post request, no response is expected");
  r->status = HTTP_OK;
  r->status_line = "200 OK";
  p_conn->close += 1;
  return OK;

2. GET requests
The problem with mod_proxy is that it tries to buffer the content, while in 
case of audio/video streaming, you have to release the content to destination 
as soon as it's possible, regardless of how small amount of data you got from 
network. The problem was that apache was getting 4 bytes of data, and tried to 
accumulate them instead of sending over to RealPlayer... The fix is to add 
FLUSH bucket to the brigade to make apache send it:
ap_proxy_http_process_response function,
const char * ct = NULL;
/* send body - but only if a body is expected */
if ((!r->header_only) &&                   /* not HEAD request */
  (r->status > 199) &&...)                 /* not any 1xx response */
  ct = apr_table_get(r->headers_out, "Content-Type");
  if ((ct != NULL) && ((stricmp(ct, "audio/x-pn-realaudio") == 0) || 
    (stricmp(ct, "application/x-pncmd") == 0)) {
    flush_rtsp_request = 1;
while (ap_get_brigade(rp->input_filters, ...) == APR_SUCCESS) {
  /* found the last brigade? */
  /*no changes*/
  else {
    if (flush_rtsp_request == 1) {
      ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
    	"proxy: adding FLUSH bucket, rc=%d", rc);
      e = apr_bucket_flush_create(c->bucket_alloc);
  /* try send what we read */
  rc = ap_pass_brigade(r->output_filters, bb);

3. HTTP protocol should be downgraded to 1.0 as RTSP-over-HTTP is using 
Comment 1 Nick Kew 2004-10-29 09:12:18 UTC
Are you saying you've hacked it to support your needs?

If so, please attach a patch that others can use if they want it - and that any
committer who knows the relevant protocols can evaluate.
Comment 2 Ilya Dogadaev 2004-10-29 11:02:57 UTC
Created attachment 13258 [details]
mod_proxy_http (from 2.0.52) with my fixes added
Comment 3 Ilya Dogadaev 2004-10-29 12:12:37 UTC
btw the version of proxy_http.c file attached to this case also fixes 
http://nagoya.apache.org/bugzilla/show_bug.cgi?id=29644 issue:

Fix details:
<!--ap_proxy_http_process_response() function
/* try send what we read */
rc = ap_pass_brigade(r->output_filters, bb);
/*Changed line follows:*/
if (rc != APR_SUCCESS || r->connection->aborted == 1 || origin->aborted == 1) {
Comment 4 Nick Kew 2004-10-29 14:37:36 UTC
Thanks.  An actual patch would be preferred, but this is broadly equivalent. 
Adding PatchAvailable keyword.

The point of a patch is to highlight diffs.  That way we could evaluate whether
it appears likely to have side-effects - such as adversely affecting performance
for normal proxying - before considering it for inclusion in the httpd codebase.
 We're more likely to adopt it if you make it easy for us!  But it's useful to
have it here anyway.
Comment 5 Amos Hayes 2005-08-26 01:31:06 UTC
I would really like to see a fix to this problem. I suspect i'm having the same issue trying to proxy 
requests to my Darwin Streaming Server.

The issue is that DSS says it can accept HTTP requests on TCP port 80 (although the default TCP port 
554 behaves no differently) but naturally, that conflics with any HTTPD on the same IP. If you *need* to 
run DSS on the same IP as Apache, but want your users (who may be firewall restricted to outbound 
port 80) to still get your streams, then you need to proxy the requests.

I have been trying unsucessfully to have mod_proxy/mod_proxy_http handle these requests. It would 
be great to see either a patch to mod_proxy_http, or a new mod_proxy_rtsp.

Any suggestions for how to help with this? Thank you!

I have DSS set up to listen on Apache is listening on external_ip:80. I have put the 
following in httpd.conf, to no avail.

LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so

ProxyRequests Off
<Proxy *>
Order deny,allow
Allow from all

<Location /media/>
SetEnv force-proxy-request-1.0 1
SetEnv proxy-nokeepalive 1

Comment 6 Nick Kew 2005-08-26 01:55:49 UTC
Whay happened when you tried Ilya's patches?  They don't look at a glance like 
something that really belongs in the main codebase, but there's nothing to 
stop you using them.  As for a new module, feel free to write one, or pay 
someone to write one for you. 
Comment 7 Amos Hayes 2005-08-26 02:40:48 UTC
Thanks for the quick reply Nick.

Wish I were clever/rich enough to solve the problem as you describe. As it is, I'm merely a home user 
trying to serve up some video of my newborn to my wife's family in the UK. I only have one external IP 
(hey... it's a fixed IP. That must be worth *some* cred). I guess I hoped using mod_proxy_http to proxy 
the claimed "RTSP over HTTP" claimed by Darwin Streaming Server would tweak some guru's interest. 
I'm actually surprised it doesn't already work. I very rarely encounter a web content problem of any kind 
for which Apache httpd hasn't had a module or directive line to solve it. :)

I'm currently digging through the "patch" (actually a modified proxy_http.c file, as you know) but 
unfortunately it is based on 2.0.52 and I have 2.0.54. The fact that Apache's source repository server is 
down and the mirrors don't carry older source means I can't get the right version to generate a diff at 
the moment. It looks like there were a fair number of changes from 2.0.52 to 2.0.54. I'll probably wait 
to get the 2.0.52 version to help generate a diff.

If I do figure it out, I'll post a proper diff for 2.0.54. If it doesn't work... oh well. Doesn't sound like it's a 
big loss to anyone.
Comment 8 William A. Rowe Jr. 2018-11-07 21:08:21 UTC
Please help us to refine our list of open and current defects; this is a mass update of old and inactive Bugzilla reports which reflect user error, already resolved defects, and still-existing defects in httpd.

As repeatedly announced, the Apache HTTP Server Project has discontinued all development and patch review of the 2.2.x series of releases. The final release 2.2.34 was published in July 2017, and no further evaluation of bug reports or security risks will be considered or published for 2.2.x releases. All reports older than 2.4.x have been updated to status RESOLVED/LATER; no further action is expected unless the report still applies to a current version of httpd.

If your report represented a question or confusion about how to use an httpd feature, an unexpected server behavior, problems building or installing httpd, or working with an external component (a third party module, browser etc.) we ask you to start by bringing your question to the User Support and Discussion mailing list, see [https://httpd.apache.org/lists.html#http-users] for details. Include a link to this Bugzilla report for completeness with your question.

If your report was clearly a defect in httpd or a feature request, we ask that you retest using a modern httpd release (2.4.33 or later) released in the past year. If it can be reproduced, please reopen this bug and change the Version field above to the httpd version you have reconfirmed with.

Your help in identifying defects or enhancements still applicable to the current httpd server software release is greatly appreciated.