@Override public AbstractStorageItem retrieveItem( ProxyRepository repository, ResourceStoreRequest request, String baseUrl) throws ItemNotFoundException, RemoteStorageException { final URL remoteURL = getAbsoluteUrlFromBase(baseUrl, request.getRequestPath()); final String itemUrl = remoteURL.toString(); final AsyncHttpClient client = getClient(repository); try { BodyDeferringInputStream ris = AHCUtils.fetchContent(client, itemUrl); // this blocks until response headers arrived Response response = ris.getAsapResponse(); // expected: 200 OK validateResponse(repository, request, "GET", itemUrl, response, 200); long length = AHCUtils.getContentLength(response, -1); long lastModified = AHCUtils.getLastModified(response, System.currentTimeMillis()); // non-reusable simplest content locator, the ris InputStream is ready to be consumed PreparedContentLocator contentLocator = new PreparedContentLocator(ris, response.getContentType()); DefaultStorageFileItem result = new DefaultStorageFileItem( repository, request, true /* canRead */, true /* canWrite */, contentLocator); result.setLength(length); result.setModified(lastModified); result.setCreated(result.getModified()); result.setRemoteUrl(itemUrl); result.getItemContext().setParentContext(request.getRequestContext()); return result; } catch (ItemNotFoundException e) { throw e; } catch (RemoteStorageException e) { throw e; } catch (Exception e) { throw new RemoteStorageException(e); } }
protected void validateResponse( final ProxyRepository repository, final ResourceStoreRequest request, final String method, final String remoteUrl, final Response response, int... expectedCodes) throws ItemNotFoundException, RemoteStorageException { // maintain the S3 flag checkForRemotePeerAmazonS3Storage(repository, response.getHeader("server")); if (response.isRedirected()) { getLogger() .info( String.format( "Proxy repository %s (id=%s) got redirected from %s, please verify your remoteUrl is up-to-date!", repository.getName(), repository.getId(), remoteUrl)); } if (AHCUtils.isAnyOfTheseStatusCodes(response, expectedCodes)) { // good, an expected one return; } // 404 NotFound if (404 == response.getStatusCode()) { throw new ItemNotFoundException(request, repository); } // 401 Unauthorized if (401 == response.getStatusCode()) { throw new RemoteAuthenticationNeededException( repository, remoteUrl, response.getStatusText()); } // 403 Forbidden if (403 == response.getStatusCode()) { throw new RemoteAccessDeniedException(repository, remoteUrl, response.getStatusText()); } // anything else "unexpected"? throw new RemoteStorageException( String.format( "Coult not perform %s against Url %s, unexpected response is %s", method, remoteUrl, response.getStatusText())); }
@Override protected boolean checkRemoteAvailability( long newerThen, ProxyRepository repository, ResourceStoreRequest request, boolean isStrict) throws RemoteStorageException { final URL remoteURL = getAbsoluteUrlFromBase(repository, request); final String itemUrl = remoteURL.toString(); final AsyncHttpClient client = getClient(repository); if (getLogger().isDebugEnabled()) { getLogger() .debug( String.format( "Checking remote availability of proxy repository \"%s\" (id=%s) on URL %s", repository.getName(), repository.getId(), itemUrl)); } // artifactory hack, it pukes on HEAD so we will try with GET if HEAD fails boolean doGet = false; Response responseObject = null; int response = 400; try { responseObject = client.prepareHead(itemUrl).execute().get(); response = responseObject.getStatusCode(); validateResponse(repository, request, "HEAD", itemUrl, responseObject, 200); } catch (ItemNotFoundException e) { return false; } catch (RemoteStorageException e) { // If HEAD failed, attempt a GET. Some repos may not support HEAD method doGet = true; getLogger().debug("HEAD method failed, will attempt GET. Exception: " + e.getMessage(), e); } catch (Exception e) { throw new RemoteStorageException(e); } finally { // HEAD returned error, but not exception, try GET before failing if (!doGet && response != 200) { // try with GET unless some known to fail responses are in doGet = (response != 401) && (response != 403); getLogger().debug("HEAD method failed, will attempt GET. Status: " + response); } } if (doGet) { try { responseObject = client.prepareGet(itemUrl).execute().get(); response = responseObject.getStatusCode(); validateResponse(repository, request, "GET", itemUrl, responseObject, 200); } catch (ItemNotFoundException e) { return false; } catch (Exception e) { throw new RemoteStorageException(e); } } // if we are not strict and remote is S3 if (!isStrict && isRemotePeerAmazonS3Storage(repository)) { // if we are relaxed, we will accept any HTTP response code below 500. This means anyway the // HTTP // transaction succeeded. This method was never really detecting that the remoteUrl really // denotes a root of // repository (how could we do that?) // this "relaxed" check will help us to "pass" S3 remote storage. return response >= 200 && response < 500; } else { // non relaxed check is strict, and will select only the OK response if (response == 200) { // we have it // we have newer if this below is true return AHCUtils.getLastModified(responseObject, System.currentTimeMillis()) > newerThen; } else if ((response >= 300 && response < 400) || response == 404) { return false; } else { throw new RemoteStorageException( "Unexpected response code while executing GET" + " method [repositoryId=\"" + repository.getId() + "\", requestPath=\"" + request.getRequestPath() + "\", remoteUrl=\"" + itemUrl + "\"]. Expected: \"SUCCESS (200)\". Received: " + response + " : " + responseObject.getStatusText()); } } }