How can I find out whether a server supports the Range header? - http

I have been trying to stream audio from a particular point by using the Range header values but I always get the song right from the beginning. I am doing this through a program so am not sure whether the problem lies in my code or on the server.
How can I find out whether the server supports the Range header param?
Thanks.

The way the HTTP spec defines it, if the server knows how to support the Range header, it will. That in turn, requires it to return a 206 Partial Content response code with a Content-Range header, when it returns content to you. Otherwise, it will simply ignore the Range header in your request, and return a 200 response code.
This might seem silly, but are you sure you're crafting a valid HTTP request header? All too commonly, I forget to specify HTTP/1.1 in the request, or forget to specify the Range specifier, such as "bytes".
Oh, and if all you want to do is check, then just send a HEAD request instead of a GET request. Same headers, same everything, just "HEAD" instead of "GET". If you receive a 206 response, you'll know Range is supported, and otherwise you'll get a 200 response.

This is for others searching how to do this. You can use curl:
curl -I http://exampleserver.com/example_video.mp4
In the header you should see
Accept-Ranges: bytes
You can go further and test retrieving a range
curl --header "Range: bytes=100-107" -I http://exampleserver.com/example_vide0.mp4
and in the headers you should see
HTTP/1.1 206 Partial Content
and
Content-Range: bytes 100-107/10000000
Content-Length: 8
[instead of 10000000 you'll see the length of the file]

Although I am a bit late in answering this question, I think my answer will help future visitors. Here is a python method that detects whether a server supports range queries or not.
def accepts_byte_ranges(self, effective_url):
"""Test if the server supports multi-part file download. Method expects effective (absolute) url."""
import pycurl
import cStringIO
import re
c = pycurl.Curl()
header = cStringIO.StringIO()
# Get http header
c.setopt(c.URL, effective_url)
c.setopt(c.NOBODY, 1)
c.setopt(c.HEADERFUNCTION, header.write)
c.perform()
c.close()
header_text = header.getvalue()
header.close()
verbose_print(header_text)
# Check if server accepts byte-ranges
match = re.search('Accept-Ranges:\s+bytes', header_text)
if match:
return True
else:
# If server explicitly specifies "Accept-Ranges: none" in the header, we do not attempt partial download.
match = re.search('Accept-Ranges:\s+none', header_text)
if match:
return False
else:
c = pycurl.Curl()
# There is still hope, try a simple byte range query
c.setopt(c.RANGE, '0-0') # First byte
c.setopt(c.URL, effective_url)
c.setopt(c.NOBODY, 1)
c.perform()
http_code = c.getinfo(c.HTTP_CODE)
c.close()
if http_code == 206: # Http status code 206 means byte-ranges are accepted
return True
else:
return False

One way is just to try, and check the response. In your case, it appears the server doesn't support ranges.
Alternatively, do a GET or HEAD on the URI, and check for the Accept-Ranges response header.

You can use GET method with 0-0 Range request header, and check whether the response code is 206 or not, which will respond with
the first and last bytes of the response body
You also can use HEAD method do the same thing as the first session which will get the same response header and code without response body
Furthermore, you can check Accept-Ranges on the response header to judge whether it can support range, but please notice if the value is none on Accept-Ranges field, it means it can't support range, and if the response header doesn't have Accept-Ranges field you also can't finger out it can't support range from it.
There is another thing you have to know if you are using 0- Range on the request header with GET method to check the response code, the response body message will be cached automatically on the TCP receive window until the cache is full.

Related

how to send a multi-part POST with curl without knowing total size of input

I am working on a project which involves sending voice over http stream, i am currently using CURL for my Http backend. I see that if i need to use "Transfer-Encoding: chunked" i need to mention the total stream size/"Content-length:" . I am currently waiting for the stream to complete from which i will know the total content size . which works but is causing significant delay . i would like to know how can i upload the data in chunks without knowing the total content length of the input.
curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, "audio",
CURLFORM_CONTENTTYPE, MULTI_PART_CONTENT_TYPE_AUDIO,
CURLFORM_STREAM, &(*(aBufffer)),
CURLFORM_CONTENTSLENGTH,bufferSize,
CURLFORM_END);
the documentation for "CURLFORM_STREAM" specifies that it is mandatory to specify "CURLFORM_CONTENTSLENGTH" . I need to use "CURLFORM_STREAM" because my buffer is big and I want curl to call "CURLOPT_READFUNCTION" to post the remaining data.
looking at the http request header specification for content-length and about the message body indicate that this header could be optional for POST request as long as the Transfer-Encoding header is specified.
The server would look for a message body if either one of the header is present.
The problem is that you would have to find a way to figure out on the server if the message have been fully received.
Tell libcurl to do the POST using chunked encoding by setting the header. See example below. You can then simply lie and set CURLFORM_CONTENTSLENGTH to some non-zero value since libcurl won't pass on a Content-Length: in its request anyway.
struct curl_slist *headerlist =
curl_slist_append(NULL, "Transfer-Encoding: chunked");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerlist);
/* pass in the created formpost data */
curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);
/* send the entire thing away */
curl_easy_perform(curl);

Paw: response body size

Paw shows a bunch of great information about a request / response including response time, but I don't see a field for request and/or response size. Is there a way to easily show the size of the response body in Paw?
You usually can see the body size as reported by the server in the Content-Length header, though it is sometimes missing in case of a Transfer-Encoding: chunked response.
There's a dynamic value to get the actual body length of the latest response, as shown below, but it isn't so convenient if you just want to see it yourself (not use it in a subsequent request):
But thanks for the input, we will add a "body size" field in the next version!

Is it OK to return most recent version of the entity in case of a 412 "Precondition failed"

When doing a PUT or DELETE with an "If-Match" header, in case the ETag sent by a client indicates staleness, rather than just returning a 412, I'd like to return the whole up-to-date entity (including its new ETag in the HTTP header), so the client does not have to perform another GET round trip, which they otherwise would certainly do - in my use-case at least they'd do in probably 100% of the cases.
I don't see anything for or against it in the docs for 412:
http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.13
And looking at, say, status code 409, it doesn't seem to be a problem in general to do whatever one likes with the response body of a 4xx error:
http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.10
So, does anything (especially in the HTTP specs) speak against return the full up-to-date entity and its ETag?
Should be fine:
All 1xx (informational), 204 (no content), and 304 (not modified)
responses MUST NOT include a message-body. All other responses do
include a message-body, although it MAY be of zero length.
Source: http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.3
What is the request? GET with If-None-Match? In that case, the server isn't supposed to return 412 anyway.
For PUT, DELETE, you certainly can return the current representation. For large representations, it will be inconvenient for clients that don't need it though.
You may also want to label the payload as representation of the resource by using the Location header; see http://greenbytes.de/tech/webdav/draft-ietf-httpbis-p2-semantics-16.html#identifying.response.associated.with.representation.

Is it possible to set some http headers while http-redirect(302 or 307)?

Is it possible to set some http headers while http-redirect(302 or 307)?
<?
header("some-header: xxx");
header("Location: http://other.domain.com/foo.php",TRUE,307);
?>
You can basically set whatever http headers you want either as the server or the client.
If you are indicating a redirect you should supply the Location header as your example suggests. You should also ensure that your response headers refer to that response rather than the resource that the client is being redirected to. i.e. your headers here could include Content-Length: 0, omit the Content-Type header and so on.
Not sure if this is what you're after - this question could do with a bit more detail.
You can always do the redirection 301/307.
There are ways to do it
1) Do it through java code :
response.setStatus(307);
response.setHeader("Location",url);
2) THe same thing can be done in JSPs.
A tip here is: Always use the setHeader function and not the addHeader function as they behave in different ways.

Is an HTTP PUT request required to include a body?

I'm having trouble finding a definite specification of this in the standard. I have an HTTP client that's not including a Content-Length: 0 header when doing a PUT request where I don't specify a body, and a server that gets confused by such requests, and I'm wondering which program I should be blaming.
HTTP requests have a body if they have a Content-Length or Transfer-Encoding header (RFC 2616 4.3). If the request has neither, it has no body, and your server should treat it as such.
That said it is unusual for a PUT request to have no body, and so if I were designing a client that really wanted to send an empty body, I'd pass Content-Length: 0. Indeed, depending on one's reading of the POST and PUT method definitions (RFC 2616 9.5, 9.6) one might argue that the body is implied to be required - but a reasonable way to handle no body would be to assume a zero-length body.
Not answering the question, but asserting how jaxrs allows me to frequent use of bodyless PUTs:
Example of bodyless put:
Give user an additional permission.
PUT /admin/users/{username}/permission/{permission}
A body is not required by the IETF standard, though the content-length should be 0 if there's no body. Use the method that's appropriate for what you're doing. If you were to put it into code, given
int x;
int f(){ return x; }
and a remote variable called r.
A post is equivalent to
r=f();
A put is equivalent to
r=x;
and a get is equivalent to
x=r;
What is being PUT (in the verb sense) onto the server if there's no content? The spec refers to the content as "the enclosed entity", but a request with no content would have no enclosed entity, and therefore nothing to put on the server.
Unless, of course, you wanted to PUT nothing onto the server, in which case you'd probably want a DELETE instead.
The content length field is required as per the following section in the HTTP/1.1 standard http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.13

Resources