зеркало из https://github.com/microsoft/reactxp.git
Filter out emulated Cache-Control: max-stale on iOS (#870)
* Filter out emulated Cache-Control: max-stale on iOS The header has the opposite effect on iOS: instead of having the cache return stale data it disables the cache altogether. The header is emulated by the component as of #853. This change adds filtering so that RN doesn't see the header. * PR feedback: add headers to state * PR feedback: use _.omit()
This commit is contained in:
Родитель
e1d8be8b7a
Коммит
71f7682712
|
@ -34,6 +34,7 @@ export interface ImageContext {
|
|||
export interface ImageState {
|
||||
forceCache?: boolean;
|
||||
lastNativeError?: any;
|
||||
headers?: Types.Headers;
|
||||
}
|
||||
|
||||
export class Image extends React.Component<Types.ImageProps, ImageState> implements React.ChildContextProvider<ImageContext> {
|
||||
|
@ -64,7 +65,7 @@ export class Image extends React.Component<Types.ImageProps, ImageState> impleme
|
|||
protected _mountedComponent: RN.Image | null = null;
|
||||
private _nativeImageWidth: number | undefined;
|
||||
private _nativeImageHeight: number | undefined;
|
||||
readonly state: ImageState = { forceCache: false, lastNativeError: undefined };
|
||||
readonly state: ImageState = { forceCache: false, lastNativeError: undefined, headers: this._buildHeaders() };
|
||||
|
||||
protected _getAdditionalProps(): RN.ImageProperties | {} {
|
||||
return {};
|
||||
|
@ -121,7 +122,7 @@ export class Image extends React.Component<Types.ImageProps, ImageState> impleme
|
|||
const sourceOrHeaderChanged = (nextProps.source !== this.props.source ||
|
||||
!_.isEqual(nextProps.headers || {}, this.props.headers || {}));
|
||||
if (sourceOrHeaderChanged) {
|
||||
this.setState({ forceCache: false, lastNativeError: undefined });
|
||||
this.setState({ forceCache: false, lastNativeError: undefined, headers: this._buildHeaders() });
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -180,7 +181,7 @@ export class Image extends React.Component<Types.ImageProps, ImageState> impleme
|
|||
return;
|
||||
}
|
||||
|
||||
if (!this.state.forceCache && this._shouldForceCacheOnError()) {
|
||||
if (!this.state.forceCache && !!this._getMaxStaleHeader()) {
|
||||
// Some platforms will not use expired cache data unless explicitly told so.
|
||||
// Let's try again with cache: 'only-if-cached'.
|
||||
this.setState({ forceCache: true, lastNativeError: e.nativeEvent.error });
|
||||
|
@ -194,16 +195,26 @@ export class Image extends React.Component<Types.ImageProps, ImageState> impleme
|
|||
}
|
||||
}
|
||||
|
||||
private _buildHeaders(): Types.Headers|undefined {
|
||||
if (this.props.headers) {
|
||||
const cacheControlHeader = this._getMaxStaleHeader();
|
||||
if (cacheControlHeader) {
|
||||
// Filter out Cache-Control: max-stale. It has the opposite effect on iOS: instead of having
|
||||
// the cache return stale data it disables the cache altogether. We emulate the header by
|
||||
// retrying with cache: 'only-if-cached'.
|
||||
return _.omit(this.props.headers, [cacheControlHeader]);
|
||||
}
|
||||
}
|
||||
return this.props.headers;
|
||||
}
|
||||
|
||||
private _buildSource(): RN.ImageSourcePropType {
|
||||
// Check if require'd image resource
|
||||
if (typeof this.props.source === 'number') {
|
||||
return this.props.source;
|
||||
}
|
||||
|
||||
const source: RN.ImageSourcePropType = { uri: this.props.source };
|
||||
if (this.props.headers) {
|
||||
source.headers = this.props.headers;
|
||||
}
|
||||
const source: RN.ImageSourcePropType = { uri: this.props.source, headers: this.state.headers };
|
||||
if (this.state.forceCache) {
|
||||
source.cache = 'only-if-cached';
|
||||
}
|
||||
|
@ -211,20 +222,17 @@ export class Image extends React.Component<Types.ImageProps, ImageState> impleme
|
|||
return source;
|
||||
}
|
||||
|
||||
private _shouldForceCacheOnError(): boolean {
|
||||
if (Platform.getType() !== 'ios') {
|
||||
return false;
|
||||
}
|
||||
if (this.props.headers) {
|
||||
private _getMaxStaleHeader(): string|undefined {
|
||||
if (Platform.getType() === 'ios' && this.props.headers) {
|
||||
for (let key in this.props.headers) {
|
||||
// We don't know how stale the cached data is so we're matching only the simple 'max-stale' attribute
|
||||
// without a value.
|
||||
if (key.toLowerCase() === 'cache-control' && this.props.headers[key].toLowerCase() === 'max-stale') {
|
||||
return true;
|
||||
return key;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// Note: This works only if you have an onLoaded handler and wait for the image to load.
|
||||
|
|
Загрузка…
Ссылка в новой задаче