mirror of
https://github.com/samsonjs/media.git
synced 2026-04-27 15:07:40 +00:00
Support POST requests with DefaultHttpDataSource/DataSpec
This commit is contained in:
parent
6b03e6a17c
commit
9dc1bfbbe7
2 changed files with 54 additions and 13 deletions
|
|
@ -20,6 +20,8 @@ import com.google.android.exoplayer.util.Assertions;
|
||||||
|
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines a region of media data.
|
* Defines a region of media data.
|
||||||
*/
|
*/
|
||||||
|
|
@ -42,6 +44,10 @@ public final class DataSpec {
|
||||||
* Identifies the source from which data should be read.
|
* Identifies the source from which data should be read.
|
||||||
*/
|
*/
|
||||||
public final Uri uri;
|
public final Uri uri;
|
||||||
|
/**
|
||||||
|
* Body for a POST request, null otherwise.
|
||||||
|
*/
|
||||||
|
public final byte[] postBody;
|
||||||
/**
|
/**
|
||||||
* The absolute position of the data in the full stream.
|
* The absolute position of the data in the full stream.
|
||||||
*/
|
*/
|
||||||
|
|
@ -124,10 +130,28 @@ public final class DataSpec {
|
||||||
*/
|
*/
|
||||||
public DataSpec(Uri uri, long absoluteStreamPosition, long position, long length, String key,
|
public DataSpec(Uri uri, long absoluteStreamPosition, long position, long length, String key,
|
||||||
int flags) {
|
int flags) {
|
||||||
|
this(uri, null, absoluteStreamPosition, position, length, key, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a {@link DataSpec} where {@link #position} may differ from
|
||||||
|
* {@link #absoluteStreamPosition}.
|
||||||
|
*
|
||||||
|
* @param uri {@link #uri}.
|
||||||
|
* @param postBody {@link #postBody}.
|
||||||
|
* @param absoluteStreamPosition {@link #absoluteStreamPosition}.
|
||||||
|
* @param position {@link #position}.
|
||||||
|
* @param length {@link #length}.
|
||||||
|
* @param key {@link #key}.
|
||||||
|
* @param flags {@link #flags}.
|
||||||
|
*/
|
||||||
|
public DataSpec(Uri uri, byte[] postBody, long absoluteStreamPosition, long position, long length,
|
||||||
|
String key, int flags) {
|
||||||
Assertions.checkArgument(absoluteStreamPosition >= 0);
|
Assertions.checkArgument(absoluteStreamPosition >= 0);
|
||||||
Assertions.checkArgument(position >= 0);
|
Assertions.checkArgument(position >= 0);
|
||||||
Assertions.checkArgument(length > 0 || length == C.LENGTH_UNBOUNDED);
|
Assertions.checkArgument(length > 0 || length == C.LENGTH_UNBOUNDED);
|
||||||
this.uri = uri;
|
this.uri = uri;
|
||||||
|
this.postBody = postBody;
|
||||||
this.absoluteStreamPosition = absoluteStreamPosition;
|
this.absoluteStreamPosition = absoluteStreamPosition;
|
||||||
this.position = position;
|
this.position = position;
|
||||||
this.length = length;
|
this.length = length;
|
||||||
|
|
@ -137,8 +161,8 @@ public final class DataSpec {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "DataSpec[" + uri + ", " + absoluteStreamPosition + ", " + position + ", " + length
|
return "DataSpec[" + uri + ", " + Arrays.toString(postBody) + ", " + absoluteStreamPosition
|
||||||
+ ", " + key + ", " + flags + "]";
|
+ ", " + position + ", " + length + ", " + key + ", " + flags + "]";
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@ import java.io.EOFException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.InterruptedIOException;
|
import java.io.InterruptedIOException;
|
||||||
|
import java.io.OutputStream;
|
||||||
import java.net.HttpURLConnection;
|
import java.net.HttpURLConnection;
|
||||||
import java.net.NoRouteToHostException;
|
import java.net.NoRouteToHostException;
|
||||||
import java.net.ProtocolException;
|
import java.net.ProtocolException;
|
||||||
|
|
@ -329,6 +330,7 @@ public class DefaultHttpDataSource implements HttpDataSource {
|
||||||
*/
|
*/
|
||||||
private HttpURLConnection makeConnection(DataSpec dataSpec) throws IOException {
|
private HttpURLConnection makeConnection(DataSpec dataSpec) throws IOException {
|
||||||
URL url = new URL(dataSpec.uri.toString());
|
URL url = new URL(dataSpec.uri.toString());
|
||||||
|
byte[] postBody = dataSpec.postBody;
|
||||||
long position = dataSpec.position;
|
long position = dataSpec.position;
|
||||||
long length = dataSpec.length;
|
long length = dataSpec.length;
|
||||||
boolean allowGzip = (dataSpec.flags & DataSpec.FLAG_ALLOW_GZIP) != 0;
|
boolean allowGzip = (dataSpec.flags & DataSpec.FLAG_ALLOW_GZIP) != 0;
|
||||||
|
|
@ -336,24 +338,27 @@ public class DefaultHttpDataSource implements HttpDataSource {
|
||||||
if (!allowCrossProtocolRedirects) {
|
if (!allowCrossProtocolRedirects) {
|
||||||
// HttpURLConnection disallows cross-protocol redirects, but otherwise performs redirection
|
// HttpURLConnection disallows cross-protocol redirects, but otherwise performs redirection
|
||||||
// automatically. This is the behavior we want, so use it.
|
// automatically. This is the behavior we want, so use it.
|
||||||
HttpURLConnection connection = configureConnection(url, position, length, allowGzip);
|
HttpURLConnection connection = makeConnection(
|
||||||
connection.connect();
|
url, postBody, position, length, allowGzip, true /* followRedirects */);
|
||||||
return connection;
|
return connection;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We need to handle redirects ourselves to allow cross-protocol redirects.
|
// We need to handle redirects ourselves to allow cross-protocol redirects.
|
||||||
int redirectCount = 0;
|
int redirectCount = 0;
|
||||||
while (redirectCount++ <= MAX_REDIRECTS) {
|
while (redirectCount++ <= MAX_REDIRECTS) {
|
||||||
HttpURLConnection connection = configureConnection(url, position, length, allowGzip);
|
HttpURLConnection connection = makeConnection(
|
||||||
connection.setInstanceFollowRedirects(false);
|
url, postBody, position, length, allowGzip, false /* followRedirects */);
|
||||||
connection.connect();
|
|
||||||
int responseCode = connection.getResponseCode();
|
int responseCode = connection.getResponseCode();
|
||||||
if (responseCode == HttpURLConnection.HTTP_MULT_CHOICE
|
if (responseCode == HttpURLConnection.HTTP_MULT_CHOICE
|
||||||
|| responseCode == HttpURLConnection.HTTP_MOVED_PERM
|
|| responseCode == HttpURLConnection.HTTP_MOVED_PERM
|
||||||
|| responseCode == HttpURLConnection.HTTP_MOVED_TEMP
|
|| responseCode == HttpURLConnection.HTTP_MOVED_TEMP
|
||||||
|| responseCode == HttpURLConnection.HTTP_SEE_OTHER
|
|| responseCode == HttpURLConnection.HTTP_SEE_OTHER
|
||||||
|| responseCode == 307 /* HTTP_TEMP_REDIRECT */
|
|| (postBody == null
|
||||||
|| responseCode == 308 /* HTTP_PERM_REDIRECT */) {
|
&& (responseCode == 307 /* HTTP_TEMP_REDIRECT */
|
||||||
|
|| responseCode == 308 /* HTTP_PERM_REDIRECT */))) {
|
||||||
|
// For 300, 301, 302, and 303 POST requests follow the redirect and are transformed into
|
||||||
|
// GET requests. For 307 and 308 POST requests are not redirected.
|
||||||
|
postBody = null;
|
||||||
String location = connection.getHeaderField("Location");
|
String location = connection.getHeaderField("Location");
|
||||||
connection.disconnect();
|
connection.disconnect();
|
||||||
url = handleRedirect(url, location);
|
url = handleRedirect(url, location);
|
||||||
|
|
@ -367,19 +372,20 @@ public class DefaultHttpDataSource implements HttpDataSource {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configures a connection, but does not open it.
|
* Configures a connection and opens it.
|
||||||
*
|
*
|
||||||
* @param url The url to connect to.
|
* @param url The url to connect to.
|
||||||
|
* @param postBody The body data for a POST request.
|
||||||
* @param position The byte offset of the requested data.
|
* @param position The byte offset of the requested data.
|
||||||
* @param length The length of the requested data, or {@link C#LENGTH_UNBOUNDED}.
|
* @param length The length of the requested data, or {@link C#LENGTH_UNBOUNDED}.
|
||||||
* @param allowGzip Whether to allow the use of gzip.
|
* @param allowGzip Whether to allow the use of gzip.
|
||||||
|
* @param followRedirects Whether to follow redirects.
|
||||||
*/
|
*/
|
||||||
private HttpURLConnection configureConnection(URL url, long position, long length,
|
private HttpURLConnection makeConnection(URL url, byte[] postBody, long position,
|
||||||
boolean allowGzip) throws IOException {
|
long length, boolean allowGzip, boolean followRedirects) throws IOException {
|
||||||
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
||||||
connection.setConnectTimeout(connectTimeoutMillis);
|
connection.setConnectTimeout(connectTimeoutMillis);
|
||||||
connection.setReadTimeout(readTimeoutMillis);
|
connection.setReadTimeout(readTimeoutMillis);
|
||||||
connection.setDoOutput(false);
|
|
||||||
synchronized (requestProperties) {
|
synchronized (requestProperties) {
|
||||||
for (Map.Entry<String, String> property : requestProperties.entrySet()) {
|
for (Map.Entry<String, String> property : requestProperties.entrySet()) {
|
||||||
connection.setRequestProperty(property.getKey(), property.getValue());
|
connection.setRequestProperty(property.getKey(), property.getValue());
|
||||||
|
|
@ -396,6 +402,17 @@ public class DefaultHttpDataSource implements HttpDataSource {
|
||||||
if (!allowGzip) {
|
if (!allowGzip) {
|
||||||
connection.setRequestProperty("Accept-Encoding", "identity");
|
connection.setRequestProperty("Accept-Encoding", "identity");
|
||||||
}
|
}
|
||||||
|
connection.setInstanceFollowRedirects(followRedirects);
|
||||||
|
connection.setDoOutput(postBody != null);
|
||||||
|
if (postBody != null) {
|
||||||
|
connection.setFixedLengthStreamingMode(postBody.length);
|
||||||
|
connection.connect();
|
||||||
|
OutputStream os = connection.getOutputStream();
|
||||||
|
os.write(postBody);
|
||||||
|
os.close();
|
||||||
|
} else {
|
||||||
|
connection.connect();
|
||||||
|
}
|
||||||
return connection;
|
return connection;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue