-
-
Notifications
You must be signed in to change notification settings - Fork 3k
added optional request headers for remote assests (android & ios) #805
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 10 commits
270fdfb
57a16b2
db1d83b
5c8e1bd
12f93b5
fefbe80
623b562
2d89a3f
f340025
49cd5b6
6cd7dfe
2649242
c67dd7b
bb2b3eb
448e57b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -23,6 +23,39 @@ export default class Video extends Component { | |
setNativeProps(nativeProps) { | ||
this._root.setNativeProps(nativeProps); | ||
} | ||
|
||
toTypeString(x) { | ||
switch (typeof x) { | ||
case "object": | ||
return x instanceof Date | ||
? x.toISOString() | ||
: JSON.stringify(x); // object, null | ||
case "undefined": | ||
return ""; | ||
default: // boolean, number, string | ||
return x.toString(); | ||
} | ||
} | ||
|
||
stringsOnlyObject(obj) { | ||
const strObj = {}; | ||
|
||
Object.keys(obj).forEach(x => { | ||
strObj[x] = this.toTypeString(obj[x]); | ||
}); | ||
|
||
return strObj; | ||
} | ||
|
||
stringsOnlyObject(obj) { | ||
const strObj = {}; | ||
|
||
Object.keys(obj).forEach(x => { | ||
strObj[x] = obj[x].toString(); | ||
}); | ||
|
||
return strObj; | ||
} | ||
|
||
seek = (time) => { | ||
this.setNativeProps({ seek: time }); | ||
|
@@ -190,6 +223,7 @@ export default class Video extends Component { | |
type: source.type || '', | ||
mainVer: source.mainVer || 0, | ||
patchVer: source.patchVer || 0, | ||
requestHeaders: source.headers ? this.stringsOnlyObject(source.headers) : {} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I believe the key here should be
throws a runtime error due to the fact that 'headers' is not a key on 'src'. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nice catch! 🙏 I've just pushed updates. I can't test it out on Android right now - it would be nice if you could verify it works. 🙌 Thanks for the reviews btw! 👍 |
||
}, | ||
onVideoLoadStart: this._onLoadStart, | ||
onVideoLoad: this._onLoad, | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,6 +16,7 @@ | |
import com.android.vending.expansion.zipfile.ZipResourceFile; | ||
import com.facebook.react.bridge.Arguments; | ||
import com.facebook.react.bridge.LifecycleEventListener; | ||
import com.facebook.react.bridge.ReadableMap; | ||
import com.facebook.react.bridge.WritableMap; | ||
import com.facebook.react.uimanager.ThemedReactContext; | ||
import com.facebook.react.uimanager.events.RCTEventEmitter; | ||
|
@@ -30,6 +31,8 @@ | |
import java.lang.Math; | ||
import java.math.BigDecimal; | ||
|
||
import javax.annotation.Nullable; | ||
|
||
@SuppressLint("ViewConstructor") | ||
public class ReactVideoView extends ScalableVideoView implements MediaPlayer.OnPreparedListener, MediaPlayer | ||
.OnErrorListener, MediaPlayer.OnBufferingUpdateListener, MediaPlayer.OnCompletionListener, MediaPlayer.OnInfoListener, LifecycleEventListener, MediaController.MediaPlayerControl { | ||
|
@@ -89,6 +92,7 @@ public String toString() { | |
|
||
private String mSrcUriString = null; | ||
private String mSrcType = "mp4"; | ||
private ReadableMap mRequestHeaders = null; | ||
private boolean mSrcIsNetwork = false; | ||
private boolean mSrcIsAsset = false; | ||
private ScalableType mResizeMode = ScalableType.LEFT_TOP; | ||
|
@@ -207,16 +211,17 @@ public void cleanupMediaPlayerResources() { | |
} | ||
} | ||
|
||
public void setSrc(final String uriString, final String type, final boolean isNetwork, final boolean isAsset) { | ||
setSrc(uriString,type,isNetwork,isAsset,0,0); | ||
public void setSrc(final String uriString, final String type, final boolean isNetwork, final boolean isAsset, final ReadableMap requestHeaders) { | ||
setSrc(uriString, type, isNetwork, isAsset, requestHeaders, 0, 0); | ||
} | ||
|
||
public void setSrc(final String uriString, final String type, final boolean isNetwork, final boolean isAsset, final int expansionMainVersion, final int expansionPatchVersion) { | ||
public void setSrc(final String uriString, final String type, final boolean isNetwork, final boolean isAsset, final ReadableMap requestHeaders, final int expansionMainVersion, final int expansionPatchVersion) { | ||
|
||
mSrcUriString = uriString; | ||
mSrcType = type; | ||
mSrcIsNetwork = isNetwork; | ||
mSrcIsAsset = isAsset; | ||
mRequestHeaders = requestHeaders; | ||
mMainVer = expansionMainVersion; | ||
mPatchVer = expansionPatchVersion; | ||
|
||
|
@@ -245,7 +250,11 @@ public void setSrc(final String uriString, final String type, final boolean isNe | |
headers.put("Cookie", cookie); | ||
} | ||
|
||
setDataSource(uriString); | ||
if (mRequestHeaders != null) { | ||
headers.putAll(toStringMap(mRequestHeaders)); | ||
} | ||
|
||
setDataSource(mThemedReactContext, parsedUrl, headers); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In master (of the main repo) no headers are being passed to Is it me or was the headers never used? Luckily |
||
} else if (isAsset) { | ||
if (uriString.startsWith("content://")) { | ||
Uri parsedUrl = Uri.parse(uriString); | ||
|
@@ -291,8 +300,13 @@ public void setSrc(final String uriString, final String type, final boolean isNe | |
} | ||
|
||
WritableMap src = Arguments.createMap(); | ||
|
||
WritableMap wRequestHeaders = Arguments.createMap(); | ||
wRequestHeaders.merge(mRequestHeaders); | ||
|
||
src.putString(ReactVideoViewManager.PROP_SRC_URI, uriString); | ||
src.putString(ReactVideoViewManager.PROP_SRC_TYPE, type); | ||
src.putMap(ReactVideoViewManager.PROP_SRC_HEADERS, wRequestHeaders); | ||
src.putBoolean(ReactVideoViewManager.PROP_SRC_IS_NETWORK, isNetwork); | ||
if(mMainVer>0) { | ||
src.putInt(ReactVideoViewManager.PROP_SRC_MAINVER, mMainVer); | ||
|
@@ -579,10 +593,10 @@ protected void onAttachedToWindow() { | |
super.onAttachedToWindow(); | ||
|
||
if(mMainVer>0) { | ||
setSrc(mSrcUriString, mSrcType, mSrcIsNetwork,mSrcIsAsset,mMainVer,mPatchVer); | ||
setSrc(mSrcUriString, mSrcType, mSrcIsNetwork, mSrcIsAsset, mRequestHeaders, mMainVer, mPatchVer); | ||
} | ||
else { | ||
setSrc(mSrcUriString, mSrcType, mSrcIsNetwork,mSrcIsAsset); | ||
setSrc(mSrcUriString, mSrcType, mSrcIsNetwork, mSrcIsAsset, mRequestHeaders); | ||
} | ||
|
||
} | ||
|
@@ -614,4 +628,28 @@ public void run() { | |
@Override | ||
public void onHostDestroy() { | ||
} | ||
|
||
/** | ||
* toStringMap converts a {@link ReadableMap} into a HashMap. | ||
* | ||
* @param readableMap The ReadableMap to be conveted. | ||
* @return A HashMap containing the data that was in the ReadableMap. | ||
* @see 'Adapted from https://github.com/artemyarulin/react-native-eval/blob/master/android/src/main/java/com/evaluator/react/ConversionUtil.java' | ||
*/ | ||
public static Map<String, String> toStringMap(@Nullable ReadableMap readableMap) { | ||
if (readableMap == null) | ||
return null; | ||
|
||
com.facebook.react.bridge.ReadableMapKeySetIterator iterator = readableMap.keySetIterator(); | ||
if (!iterator.hasNextKey()) | ||
return null; | ||
|
||
Map<String, String> result = new HashMap<>(); | ||
while (iterator.hasNextKey()) { | ||
String key = iterator.nextKey(); | ||
result.put(key, readableMap.getString(key)); | ||
} | ||
|
||
return result; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -321,14 +321,21 @@ - (AVPlayerItem*)playerItemForSource:(NSDictionary *)source | |
bool isAsset = [RCTConvert BOOL:[source objectForKey:@"isAsset"]]; | ||
NSString *uri = [source objectForKey:@"uri"]; | ||
NSString *type = [source objectForKey:@"type"]; | ||
|
||
NSDictionary *headers = [source objectForKey:@"requestHeaders"]; | ||
|
||
NSURL *url = (isNetwork || isAsset) ? | ||
[NSURL URLWithString:uri] : | ||
[[NSURL alloc] initFileURLWithPath:[[NSBundle mainBundle] pathForResource:uri ofType:type]]; | ||
|
||
if (isNetwork) { | ||
NSMutableDictionary *assetOptions = [[NSMutableDictionary alloc]init]; | ||
if ([headers count] > 0) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This will ignore cookies if you opt to use headers. You should build up the options object so both are supported. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ahh, good point! 🙌 I see it now 👏 |
||
[assetOptions setObject:@headers forKey:@"AVURLAssetHTTPHeaderFieldsKey"] | ||
} | ||
NSArray *cookies = [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookies]; | ||
AVURLAsset *asset = [AVURLAsset URLAssetWithURL:url options:@{AVURLAssetHTTPCookiesKey : cookies}]; | ||
[assetOptions setObject:@cookies forKey:@AVURLAssetHTTPCookiesKey] | ||
|
||
AVURLAsset *asset = [AVURLAsset URLAssetWithURL:url options:assetOptions]; | ||
return [AVPlayerItem playerItemWithAsset:asset]; | ||
} | ||
else if (isAsset) { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will set objects to
[object Object]
- do we want a check here fortypeof obj[x]
and to useJSON.stringify
in those cases?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes you're correct - I was kinda of unsure whether to leave it or do a "smarter" string conversion. After your review, I choose the latter. 👍
Conversion is as follows:
prototype.toString
JSON.stringify
'prototype.toISOString
undefined
=> returns empty string