예제 #1
0
        public IAsyncRequest Request(string uri, Action <Response> callback, int timeout = 10)
        {
            byte[] data = null;

            foreach (var cache in _caches)
            {
                data = cache.Get(uri);
                if (null != data)
                {
                    break;
                }
            }

            if (null != data)
            {
                foreach (var cache in _caches)
                {
                    cache.Add(uri, data);
                }

                callback(Response.FromCache(data));
                return(new MemoryCacheAsyncRequest(uri));
            }
            else
            {
                string cacheKey = uri;

                var uriBuilder = new UriBuilder(uri);

                if (!string.IsNullOrEmpty(_accessToken))
                {
                    string accessTokenQuery = "access_token=" + _accessToken;
                    if (uriBuilder.Query != null && uriBuilder.Query.Length > 1)
                    {
                        uriBuilder.Query = uriBuilder.Query.Substring(1) + "&" + accessTokenQuery;
                    }
                    else
                    {
                        uriBuilder.Query = accessTokenQuery;
                    }
                }

                //UnityEngine.Debug.Log("CachingWebFileSource: sending HTTPRequest " + uri);

                return(IAsyncRequestFactory.CreateRequest(
                           uriBuilder.ToString(),
                           (Response r) =>
                {
                    if (!r.HasError)
                    {
                        foreach (var cache in _caches)
                        {
                            cache.Add(cacheKey, r.Data);
                        }
                    }
                    callback(r);
                }, timeout));
            }
        }
예제 #2
0
        private IAsyncRequest requestTileAndCache(string url, string mapId, CanonicalTileId tileId, int timeout, Action <Response> callback)
        {
            return(IAsyncRequestFactory.CreateRequest(
                       url,
                       (Response r) =>
            {
                // if the request was successful add tile to all caches
                if (!r.HasError && null != r.Data)
                {
                    //UnityEngine.Debug.Log(uri);
                    string eTag = string.Empty;
                    DateTime?lastModified = null;

                    if (!r.Headers.ContainsKey("ETag"))
                    {
                        UnityEngine.Debug.LogWarningFormat("no 'ETag' header present in response for {0}", url);
                    }
                    else
                    {
                        eTag = r.Headers["ETag"];
                    }

                    // not all APIs populate 'Last-Modified' header
                    // don't log error if it's missing
                    if (r.Headers.ContainsKey("Last-Modified"))
                    {
                        lastModified = DateTime.ParseExact(r.Headers["Last-Modified"], "r", null);
                    }

                    // propagate to all caches forcing update
                    foreach (var cache in _caches)
                    {
                        cache.Add(
                            mapId
                            , tileId
                            , new CacheItem()
                        {
                            Data = r.Data,
                            ETag = eTag,
                            LastModified = lastModified
                        }
                            , true                                     // force insert/update
                            );
                    }
                }
                if (null != callback)
                {
                    r.IsUpdate = true;
                    callback(r);
                }
            }, timeout));
        }
예제 #3
0
        public IAsyncRequest Request(
            string uri
            , Action <Response> callback
            , int timeout            = 10
            , CanonicalTileId tileId = new CanonicalTileId()
            , string mapId           = null
            )
        {
            if (string.IsNullOrEmpty(mapId))
            {
                throw new Exception("Cannot cache without a map id");
            }

            CacheItem cachedItem = null;

            // go through existing caches and check if we already have the requested tile available
            foreach (var cache in _caches)
            {
                cachedItem = cache.Get(mapId, tileId);
                if (null != cachedItem)
                {
                    break;
                }
            }

            var finalUrl = uri + "?" + TelemetryFactory.EventQuery;

            if (!string.IsNullOrEmpty(_accessToken))
            {
                finalUrl += "&access_token=" + _accessToken;
            }

#if MAPBOX_DEBUG_CACHE
            string methodName = _className + "." + new System.Diagnostics.StackFrame().GetMethod().Name;
#endif

            // if tile was available call callback with it, propagate to all other caches and check if a newer one is available
            if (null != cachedItem)
            {
#if MAPBOX_DEBUG_CACHE
                UnityEngine.Debug.LogFormat("{0} {1} {2} {3}", methodName, mapId, tileId, null != cachedItem.Data ? cachedItem.Data.Length.ToString() : "cachedItem.Data is NULL");
#endif
                // immediately return cached tile
                callback(Response.FromCache(cachedItem.Data));

                // check for updated tiles online if this is enabled in the settings
                if (_autoRefreshCache)
                {
                    // check if tile on the web is newer than the one we already have locally
                    IAsyncRequestFactory.CreateRequest(
                        finalUrl,
                        (Response headerOnly) =>
                    {
                        // on error getting information from API just return. tile we have locally has already been returned above
                        if (headerOnly.HasError)
                        {
                            return;
                        }

                        // TODO: remove Debug.Log before PR
                        //UnityEngine.Debug.LogFormat(
                        //	"{1}{0}cached:{2}{0}header:{3}"
                        //	, Environment.NewLine
                        //	, finalUrl
                        //	, cachedItem.ETag
                        //	, headerOnly.Headers["ETag"]
                        //);

                        // data from cache is the same as on the web:
                        //   * tile has already been returned above
                        //   * make sure all all other caches have it too, but don't force insert via cache.add(false)
                        // additional ETag empty check: for backwards compability with old caches
                        if (!string.IsNullOrEmpty(cachedItem.ETag) && cachedItem.ETag.Equals(headerOnly.Headers["ETag"]))
                        {
                            foreach (var cache in _caches)
                            {
                                cache.Add(mapId, tileId, cachedItem, false);
                            }
                        }
                        else
                        {
                            // TODO: remove Debug.Log before PR
                            UnityEngine.Debug.LogWarningFormat(
                                "updating cached tile {1} mapid:{2}{0}cached etag:{3}{0}remote etag:{4}{0}{5}"
                                , Environment.NewLine
                                , tileId
                                , mapId
                                , cachedItem.ETag
                                , headerOnly.Headers["ETag"]
                                , finalUrl
                                );

                            // request updated tile and pass callback to return new data to subscribers
                            requestTileAndCache(finalUrl, mapId, tileId, timeout, callback);
                        }
                    }
                        , timeout
                        , HttpRequestType.Head
                        );
                }

                return(new MemoryCacheAsyncRequest(uri));
            }
            else
            {
                // requested tile is not in any of the caches yet, get it
#if MAPBOX_DEBUG_CACHE
                UnityEngine.Debug.LogFormat("{0} {1} {2} not cached", methodName, mapId, tileId);
#endif
                return(requestTileAndCache(finalUrl, mapId, tileId, timeout, callback));
            }
        }
예제 #4
0
        public IAsyncRequest Request(
            string uri
            , Action <Response> callback
            , int timeout            = 10
            , CanonicalTileId tileId = new CanonicalTileId()
            , string mapId           = null
            )
        {
            if (string.IsNullOrEmpty(mapId))
            {
                throw new Exception("Cannot cache without a map id");
            }

            byte[] data = null;

            // go through existing caches and check if we already have the requested tile available
            foreach (var cache in _caches)
            {
                data = cache.Get(mapId, tileId);
                if (null != data)
                {
                    break;
                }
            }

            // if tile was available propagate to all other caches and return
            if (null != data)
            {
                foreach (var cache in _caches)
                {
                    cache.Add(mapId, tileId, data);
                }

                callback(Response.FromCache(data));
                return(new MemoryCacheAsyncRequest(uri));
            }
            else
            {
                // requested tile is not in any of the caches yet, get it
                var uriBuilder = new UriBuilder(uri);

                if (!string.IsNullOrEmpty(_accessToken))
                {
                    string accessTokenQuery = "access_token=" + _accessToken;
                    if (uriBuilder.Query != null && uriBuilder.Query.Length > 1)
                    {
                        uriBuilder.Query = uriBuilder.Query.Substring(1) + "&" + accessTokenQuery;
                    }
                    else
                    {
                        uriBuilder.Query = accessTokenQuery;
                    }
                }

                return(IAsyncRequestFactory.CreateRequest(
                           uriBuilder.ToString(),
                           (Response r) =>
                {
                    // if the request was successful add tile to all caches
                    if (!r.HasError && null != r.Data)
                    {
                        foreach (var cache in _caches)
                        {
                            cache.Add(mapId, tileId, r.Data);
                        }
                    }
                    callback(r);
                }, timeout));
            }
        }