OkHttpClient cannot resolve method setCache - retrofit

I'm trying to set a cache for Retrofit so that it does not have to retrieve the data constantly. I followed this SO as it appears to be in the right direction of what I need.
I have the following (which is identical from the SO)
OkHttpClient client = new OkHttpClient();
client.networkInterceptors().add(REWRITE_CACHE_CONTROL_INTERCEPTOR);
File httpCacheDirectory = new File(getCacheDir(), "responses");
int cacheSize = 10*1024*1024;
Cache cache = new Cache(httpCacheDirectory, cacheSize);
client.setCache(cache);
However, client.setCache(cache) returns an error cannot resolve method setCache.
What am I doing wrong here? I have retrofit 2.1.0 and okhttp3 3.4.1

In 3.x a bunch of methods on OkHttpClient were moved into methods on OkHttpClient.Builder. You want something like this:
File httpCacheDirectory = new File(getCacheDir(), "responses");
int cacheSize = 10*1024*1024;
Cache cache = new Cache(httpCacheDirectory, cacheSize);
OkHttpClient client = new OkHttpClient.Builder()
.addNetworkInterceptor(REWRITE_CACHE_CONTROL_INTERCEPTOR)
.cache(cache)
.build();

File httpCacheDirectory = new File(getCacheDir(), "responses");
int cacheSize = 10*1024*1024;
Cache cache = new Cache(httpCacheDirectory, cacheSize);
OkHttpClient client = new OkHttpClient.Builder()
.addNetworkInterceptor(REWRITE_CACHE_CONTROL_INTERCEPTOR)
.cache(cache)
.build();
/////////and
public static final Interceptor REWRITE_CACHE_CONTROL_INTERCEPTOR = new Interceptor() {
#Override
public Response intercept(Chain chain) throws IOException {
Response originalResponse = chain.proceed(chain.request());
if (Global.networkConnection()) {
int maxAge = 60; // read from cache for 1 minute
return originalResponse.newBuilder()
.header("Cache-Control", "public, max-age=" + maxAge)
.build();
} else {
int maxStale = 60 * 60 * 24 * 28; // tolerate 4-weeks stale
return originalResponse.newBuilder()
.header("Cache-Control", "public, only-if-cached, max-stale=" + maxStale)
.build();
}
}
};

Related

Microsoft.Exchange.WebServices.Data.ServiceResponseException: 'There are no public folder servers available.'

further to this question, i have the same problem. PubFolder on Prem , users in O365
I have fetched and added the routing headers from Glen's post but still get the error
GetToken works...
https://learn.microsoft.com/en-us/exchange/client-developer/exchange-web-services/how-to-authenticate-an-ews-application-by-using-oauth
GetX headers works...
https://learn.microsoft.com/en-us/exchange/client-developer/exchange-web-services/public-folder-access-with-ews-in-exchange
--->> ewsClient.FindFolders(WellKnownFolderName.PublicFoldersRoot, new FolderView(10))
Microsoft.Exchange.WebServices.Data.ServiceResponseException: 'There are no public folder servers available.'
static async System.Threading.Tasks.Task Test3()
{
string ClientId = ConfigurationManager.AppSettings["appId"];
string TenantId = ConfigurationManager.AppSettings["tenantId"];
string secret = ConfigurationManager.AppSettings["clientSecret"];
string uMbox = ConfigurationManager.AppSettings["userId"];
string uPwd = ConfigurationManager.AppSettings["userPWD"];
// Using Microsoft.Identity.Client 4.22.0
//https://learn.microsoft.com/en-us/exchange/client-developer/exchange-web-services/how-to-authenticate-an-ews-application-by-using-oauth//
var cca = ConfidentialClientApplicationBuilder
.Create(ClientId)
.WithClientSecret(secret)
.WithTenantId(TenantId)
.Build();
var ewsScopes = new string[] { "https://outlook.office365.com/.default" };
try
{
var authResult = await cca.AcquireTokenForClient(ewsScopes)
.ExecuteAsync();
// Configure the ExchangeService with the access token
var ewsClient = new ExchangeService();
ewsClient.Url = new Uri("https://outlook.office365.com/EWS/Exchange.asmx");
ewsClient.Credentials = new OAuthCredentials(authResult.AccessToken);
ewsClient.ImpersonatedUserId =
new ImpersonatedUserId(ConnectingIdType.SmtpAddress, uMbox);
AutodiscoverService autodiscoverService = GetAutodiscoverService(uMbox, uPwd);
GetUserSettingsResponse userResponse = GetUserSettings(autodiscoverService, uMbox, 3, UserSettingName.PublicFolderInformation, UserSettingName.InternalRpcClientServer);
string pfAnchorHeader= userResponse.Settings[UserSettingName.PublicFolderInformation].ToString();
string pfMailboxHeader = userResponse.Settings[UserSettingName.InternalRpcClientServer].ToString(); ;
// Make an EWS call
var folders = ewsClient.FindFolders(WellKnownFolderName.MsgFolderRoot, new FolderView(10));
foreach (var folder in folders)
{
Console.WriteLine($"Folder: {folder.DisplayName}");
}
//get Public folder root
//Include x-anchormailbox header
Console.WriteLine("X-AnchorMailbox value for public folder hierarchy requests: {0}", pfAnchorHeader);
Console.WriteLine("X-PublicFolderMailbox value for public folder hierarchy requests: {0}", pfMailboxHeader);
//var test3 = GetMailboxGuidAddress(ewsClient, pfAnchorHeader, pfMailboxHeader, uMbox);
///https://learn.microsoft.com/en-us/exchange/client-developer/exchange-web-services/how-to-route-public-folder-content-requests <summary>
ewsClient.HttpHeaders.Add("X-AnchorMailbox", userResponse.Settings[UserSettingName.PublicFolderInformation].ToString());
//ewsClient.HttpHeaders.Add("X-AnchorMailbox", "SharedPublicFolder#contoso.com");
ewsClient.HttpHeaders.Add("X-PublicFolderMailbox", userResponse.Settings[UserSettingName.InternalRpcClientServer].ToString());
try
{
var pubfolders = ewsClient.FindFolders(WellKnownFolderName.PublicFoldersRoot, new FolderView(10));
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
throw;
}
foreach (var folder in folders)
{
Console.WriteLine($"Folder: {folder.DisplayName}");
}
}
catch (MsalException ex)
{
Console.WriteLine($"Error acquiring access token: {ex}");
}
catch (Exception ex)
{
Console.WriteLine($"Error: {ex}");
}
if (System.Diagnostics.Debugger.IsAttached)
{
Console.WriteLine("Hit any key to exit...");
Console.ReadKey();
}
}
public static AutodiscoverService GetAutodiscoverService(string username, string pwd)
{
AutodiscoverService adAutoDiscoverService = new AutodiscoverService();
adAutoDiscoverService.Credentials = new WebCredentials(username, pwd);
adAutoDiscoverService.EnableScpLookup = true;
adAutoDiscoverService.RedirectionUrlValidationCallback = RedirectionUrlValidationCallback;
adAutoDiscoverService.PreAuthenticate = true;
adAutoDiscoverService.TraceEnabled = true;
adAutoDiscoverService.KeepAlive = false;
return adAutoDiscoverService;
}
public static GetUserSettingsResponse GetUserSettings(
AutodiscoverService service,
string emailAddress,
int maxHops,
params UserSettingName[] settings)
{
Uri url = null;
GetUserSettingsResponse response = null;
for (int attempt = 0; attempt < maxHops; attempt++)
{
service.Url = url;
service.EnableScpLookup = (attempt < 2);
response = service.GetUserSettings(emailAddress, settings);
if (response.ErrorCode == AutodiscoverErrorCode.RedirectAddress)
{
url = new Uri(response.RedirectTarget);
}
else if (response.ErrorCode == AutodiscoverErrorCode.RedirectUrl)
{
url = new Uri(response.RedirectTarget);
}
else
{
return response;
}
}
throw new Exception("No suitable Autodiscover endpoint was found.");
}
Your code won't work against an OnPrem Public folder tree as EWS in Office365 won't proxy to an OnPrem Exchange Org (even if hybrid is setup). (Outlook MAPI is a little different and allows this via versa setup but in that case it never proxies either it just makes a different connection to that store and its all the Outlook client doing this).
Because your trying to use the client credentials oauth flow for that to work onPrem you must have setup hybrid modern authentication https://learn.microsoft.com/en-us/microsoft-365/enterprise/hybrid-modern-auth-overview?view=o365-worldwide. Then you need to acquire a token with an audience set to the local OnPrem endpoint. (this is usually just your onPrem ews endpoint's host name but it should be one of the service principal names configured in your hybrid auth setup Get-MsolServicePrincipal). So in your code you would change
var ewsScopes = new string[] { "https://outlook.office365.com/.default" };
to
var ewsScopes = new string[] { "https://OnPrem.whatever.com/.default" };
which will then give you a token with an audience set for the onprem server then you need to send the EWS request to that endpoint so change that eg
ewsClient.Url = new Uri("https://OnPrem.whatever.com/EWS/Exchange.asmx");
if Hybird Modern Auth is setup then you need to default back to use Integrated or Basic Authenticaiton.

Setting SSL Parameters on Apache http5 Client

I am upgrading from Apache httpcomponents 4 to version 5 in order to get http2/http1.1 support. I need to specify the ciphers my client offers. I assume that H2/1.1 ALPN is the default behavior for the AsyncHttpClient.
Here is my current code for the httpcomponents 4 client
// TLS
SSLConnectionSocketFactory sslConnectionFactory = new SSLConnectionSocketFactory(
SSLContexts.createDefault(),
new String[] { "TLSv1.2" },
new String[] {"TLS_AES_128_GCM_SHA256", "TLS_AES_256_GCM_SHA384",
"TLS_CHACHA20_POLY1305_SHA256", "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256",
"TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256", "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA", "TLS_RSA_WITH_AES_128_GCM_SHA256",
"TLS_RSA_WITH_AES_256_GCM_SHA384", "TLS_RSA_WITH_AES_128_CBC_SHA",
"TLS_RSA_WITH_AES_256_CBC_SHA"},
SSLConnectionSocketFactory.getDefaultHostnameVerifier());
// Proxy
HttpHost proxyhost = new HttpHost(proxyAddress, proxyPort);
HttpRoutePlanner routePlanner = new DefaultProxyRoutePlanner(proxyhost);
CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(
new AuthScope(proxyAddress, proxyPort),
new UsernamePasswordCredentials(proxyUsername, proxyPassword)
);
httpClient = HttpClients.custom()
.setRoutePlanner(routePlanner)
.setSSLSocketFactory(sslConnectionFactory)
.setDefaultCredentialsProvider(credentialsProvider)
.setRedirectStrategy(new LaxRedirectStrategy())
.setDefaultCookieStore(cookieStore)
.build();
Everything seems to be roughly the same for creating the asyc client except specifying the SSL factory. So setting the TLS parameters appears to take a different route. I've spent about an hour looking for examples and documentation with no luck. Some examples show a class called TLSConfig, but I can't find any documentation on it.
Any help is greatly appreciated.
You need to build a custom TlsStrategy pretty much the same way as shown in the "Custom SSL context" example on the project website [1]
TLSConfig will be available as of 5.2 release which is going to go BETA soon.
final TlsStrategy tlsStrategy = ClientTlsStrategyBuilder.create()
.setTlsVersions(TLS.V_1_2)
.setCiphers("TLS_AES_128_GCM_SHA256", "TLS_AES_256_GCM_SHA384",
"TLS_CHACHA20_POLY1305_SHA256", "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256",
"TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256", "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA", "TLS_RSA_WITH_AES_128_GCM_SHA256",
"TLS_RSA_WITH_AES_256_GCM_SHA384", "TLS_RSA_WITH_AES_128_CBC_SHA",
"TLS_RSA_WITH_AES_256_CBC_SHA")
.build();
final PoolingAsyncClientConnectionManager cm = PoolingAsyncClientConnectionManagerBuilder.create()
.setTlsStrategy(tlsStrategy)
.build();
try (final CloseableHttpAsyncClient client = HttpAsyncClients.custom()
.setConnectionManager(cm)
.build()) {
client.start();
final HttpHost target = new HttpHost("https", "httpbin.org");
final HttpClientContext clientContext = HttpClientContext.create();
final SimpleHttpRequest request = SimpleRequestBuilder.get()
.setHttpHost(target)
.setPath("/")
.build();
System.out.println("Executing request " + request);
final Future<SimpleHttpResponse> future = client.execute(
SimpleRequestProducer.create(request),
SimpleResponseConsumer.create(),
clientContext,
new FutureCallback<SimpleHttpResponse>() {
#Override
public void completed(final SimpleHttpResponse response) {
System.out.println(request + "->" + new StatusLine(response));
final SSLSession sslSession = clientContext.getSSLSession();
if (sslSession != null) {
System.out.println("SSL protocol " + sslSession.getProtocol());
System.out.println("SSL cipher suite " + sslSession.getCipherSuite());
}
System.out.println(response.getBody());
}
#Override
public void failed(final Exception ex) {
System.out.println(request + "->" + ex);
}
#Override
public void cancelled() {
System.out.println(request + " cancelled");
}
});
future.get();
System.out.println("Shutting down");
client.close(CloseMode.GRACEFUL);
[1] https://hc.apache.org/httpcomponents-client-5.1.x/examples-async.html

.NET Core reverse proxy middleware and signalR

I need to do a reverse proxy middleware in ASP.NET Core. I have something like this. But it doesn't work with SignalR.
Reverse proxy has address 192.168.187.72:5000; SignalR 192.168.187.62:5000. Client connects to proxy, proxy changes the url to SignalR hub url, but in client I always get this error:
The server disconnected before the handshake could be started
Code:
public ReverseProxyMiddleware(RequestDelegate nextMiddleware,ILogger<ReverseProxyMiddleware> logger)
{
_nextMiddleware = nextMiddleware;
_logger = logger;
}
public async Task Invoke(HttpContext context)
{
var targetUri = BuildTargetUri(context.Request);
if (targetUri != null)
{
var targetRequestMessage = CreateTargetMessage(context, targetUri);
using (var responseMessage = await _httpClient.SendAsync(targetRequestMessage, HttpCompletionOption.ResponseHeadersRead, context.RequestAborted))
{
context.Response.StatusCode = (int)responseMessage.StatusCode;
CopyFromTargetResponseHeaders(context, responseMessage);
await responseMessage.Content.CopyToAsync(context.Response.Body);
}
return;
}
await _nextMiddleware(context);
}
private HttpRequestMessage CreateTargetMessage(HttpContext context, Uri targetUri)
{
var requestMessage = new HttpRequestMessage();
CopyFromOriginalRequestContentAndHeaders(context, requestMessage);
requestMessage.RequestUri = targetUri;
requestMessage.Headers.Host = targetUri.Host;
requestMessage.Method = GetMethod(context.Request.Method);
return requestMessage;
}
private void CopyFromOriginalRequestContentAndHeaders(HttpContext context, HttpRequestMessage requestMessage)
{
var requestMethod = context.Request.Method;
var streamContent = new StreamContent(context.Request.Body);
requestMessage.Content = streamContent;
foreach (var header in context.Request.Headers)
{
requestMessage.Content?.Headers.TryAddWithoutValidation(header.Key, header.Value.ToArray());
}
}
private void CopyFromTargetResponseHeaders(HttpContext context, HttpResponseMessage responseMessage)
{
foreach (var header in responseMessage.Headers)
{
context.Response.Headers[header.Key] = header.Value.ToArray();
}
foreach (var header in responseMessage.Content.Headers)
{
context.Response.Headers[header.Key] = header.Value.ToArray();
}
context.Response.Headers.Remove("transfer-encoding");
}
private static HttpMethod GetMethod(string method)
{
if (HttpMethods.IsDelete(method)) return HttpMethod.Delete;
if (HttpMethods.IsGet(method)) return HttpMethod.Get;
if (HttpMethods.IsHead(method)) return HttpMethod.Head;
if (HttpMethods.IsOptions(method)) return HttpMethod.Options;
if (HttpMethods.IsPost(method)) return HttpMethod.Post;
if (HttpMethods.IsPut(method)) return HttpMethod.Put;
if (HttpMethods.IsTrace(method)) return HttpMethod.Trace;
return new HttpMethod(method);
}
private Uri BuildTargetUri(HttpRequest request)
{
Uri targetUri = null;
StringValues clientId = string.Empty;
targetUri = new Uri($"http://192.168.187.62:5000{request.Path}{request.QueryString}");
_logger.LogInformation($"Request URL {request.Host + request.Path + request.QueryString} Target URL {targetUri.ToString()}");
return targetUri;
}
Are you sure you want to create such functionality manually?
There are many great libraries for reverse proxying, Microsoft has a new project called YARP (https://microsoft.github.io/reverse-proxy/) which is an open source reverse proxy told to be high performance and highly customizable.
If you like I can show you a sample how you can use yarp in an ASP.NET Core app.

Reverse proxy in .NET Core Middleware “set-cookie” response does not set in browser and not showing in HttpResponseMessage

Here I am making a reverse proxy server to bypass an ASP.NET web application (following this tutorial). I am trying to read the session ID cookie from HttpResponseMessage. I used a cookie container as well but am unable to find it. Implemented in ASP.NET core invoke method, session is working properly but unable to catch session ID in request or response.
public async Task Invoke(HttpContext context, IBrowserDetector detector)
{
//context.Session.SetString(SessionKeyName, "The Doctor");
var browser = detector.Browser;
var targetUri = BuildTargetUri(context.Request);
if (context.Request.Method != HttpMethod.Get.Method)
{
var remoteIp = context.Connection.RemoteIpAddress;
//var gg= context.Request.Headers.ContainsKey.;
var clienttdatetime = context.Request.Headers["Date"].ToString();
//_logger.LogDebug("Request from Remote IP address: {RemoteIp}", remoteIp);
var badIp = true;
var bytes = remoteIp.GetAddressBytes();
//var testIp = IPAddress.Parse(address);
//if (testIp.GetAddressBytes().SequenceEqual(bytes))
//{
// badIp = false;
// break;
//}
if (remoteIp.IsIPv4MappedToIPv6)
{
remoteIp = remoteIp.MapToIPv4();
}
IPAddress remoteIpAddress = context.Request.HttpContext.Connection.RemoteIpAddress;
string result = "";
if (remoteIpAddress != null)
{
// If we got an IPV6 address, then we need to ask the network for the IPV4 address
// This usually only happens when the browser is on the same machine as the server.
if (remoteIpAddress.AddressFamily == System.Net.Sockets.AddressFamily.InterNetworkV6)
{
remoteIpAddress = System.Net.Dns.GetHostEntry(remoteIpAddress).AddressList
.First(x => x.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork);
}
result = remoteIpAddress.ToString();
}
if (badIp)
{
//_logger.LogWarning(
// "Forbidden Request from Remote IP address: {RemoteIp}", remoteIp);
//context.Response.StatusCode = StatusCodes.Status403Forbidden;
//return;
}
}
if (targetUri != null)
{
CookieContainer cookies = new CookieContainer();
HttpClientHandler handler = new HttpClientHandler();
handler.CookieContainer = cookies;
var targetRequestMessage = CreateTargetMessage(context, targetUri);
using (var responseMessage = await _httpClient.SendAsync(targetRequestMessage, HttpCompletionOption.ResponseHeadersRead, context.RequestAborted))
{
IEnumerable<Cookie> responseCookies = cookies.GetCookies(targetUri).Cast<Cookie>();
foreach (Cookie cookie_ in responseCookies)
Console.WriteLine(cookie_.Name + ": " + cookie_.Value);
// ExtractCookiesFromResponse(responseMessage);
context.Response.StatusCode = (int)responseMessage.StatusCode;
CopyFromTargetResponseHeaders(context, responseMessage);
await responseMessage.Content.CopyToAsync(context.Response.Body);
//if(responseMessage.RequestMessage.RequestUri.ToString()== "http://localhost:51125/Menu.aspx")
//{
//Uri uri = new Uri("http://localhost:5000/login.aspx");
//Build the request
//Uri site = targetUri;
// HttpWebRequest request = (HttpWebRequest)WebRequest.Create(site);
// CookieContainer cookiesq = new CookieContainer();
// request.CookieContainer = cookiesq;
// //Print out the number of cookies before the response (of course it will be blank)
// Console.WriteLine(cookiesq.GetCookieHeader(site),"1");
// //Get the response and print out the cookies again
// using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
// {
// Console.WriteLine(cookiesq.GetCookieHeader(site), "2");
// }
// Console.ReadKey();
//}
var cookie = context.Request.Cookies["ASP.NET_SessionId"];
}
return;
}
await _nextMiddleware(context);
}
------------------------------------------------------------------------------------
public static IDictionary<string, string> ExtractCookiesFromResponse(HttpResponseMessage response)
{
IDictionary<string, string> result = new Dictionary<string, string>();
IEnumerable<string> values;
if (response.Headers.TryGetValues("Set-Cookie", out values))
{
SetCookieHeaderValue.ParseList(values.ToList()).ToList().ForEach(cookie =>
{
result.Add(cookie.Name.ToString(), cookie.Value.ToString());
});
}
return result;
}
As far as I can see, you created the HttpClientHandler but didn't use it to build the HttpClient to make your request. You are still using the static _httpClient that nothing knows about the cookie container you created.
This should be the reason why you get the CookieContainer still empty.
Take a look here to learn how to get cookies from an HttpResponseMessage.
CookieContainer cookies = new CookieContainer();
HttpClientHandler handler = new HttpClientHandler();
handler.CookieContainer = cookies;
_httpClient = new HttpClient(handler);
var targetRequestMessage = CreateTargetMessage(context, targetUri);
using (var responseMessage = await _httpClient.SendAsync(targetRequestMessage, HttpCompletionOption.ResponseHeadersRead, context.RequestAborted))
{
//var responseCookies = cookies.GetCookies(targetUri).Cast<Cookie>();
IEnumerable<Cookie> responseCookies = cookies.GetCookies(targetUri).Cast<Cookie>();
foreach (Cookie cookie in responseCookies)
{
if(cookie.Name=="ASP.NET_SessionId")
{
Console.WriteLine(cookie.Name + ": " + cookie.Value);
context.Response.Headers.Add("Set-Cookie", cookie.Name+"="+cookie.Value);
}
}

If I have a spring mvc rest controller returning byte[], how would I download to my android app using volley?

I need to implement a list view containing a thumbnail, and this thumbnail is loaded using volley networkimageview. How would I implement this if my controller looks like this:
#RequestMapping (value="/rest/getphoto/", produces=MediaType.IMAGE_PNG_VALUE)
public #ResponseBody byte [] get Image (#RequestParam ("imageId"));
I've found many examples regarding the usage of volley but they are not helping me. Besides, I am using secure connection. Thanks in advance.
EDIT: I'm including controller code in my spring mvc project and the portion of code in my android client requesting an image.
* Spring MVC *
#RequestMapping(value = "/rest/singlephoto/", method = RequestMethod.GET, produces = MediaType.IMAGE_PNG_VALUE)
public #ResponseBody byte[] base64ImageForAndroid(#RequestParam("photoId") String photoIdParam, HttpServletRequest request)
{
String pathToLoad = "/path/default.png";
//HashMap<String, String> retVal = new HashMap<String, String>();
byte[] retVal;
try
{
long photoId = Long.parseLong(photoIdParam);
Photo photo = photoManager.getSinglePhoto(photoId);
if (photo != null)
pathToLoad = photo.getPath();
}
catch (NumberFormatException ex)
{
}
finally
{
try
{
File file = new File(pathToLoad);
retVal = FileUtils.readFileToByteArray(file);
}
catch (IOException ex)
{
retVal = null;
}
}
return retVal;
* Android Client Requesting with volley *
Bitmap thumb = imageCache.get(item.getThumbnailUrl() + "thumb");
if (thumb == null)
{
HttpHeaders headers = new HttpHeaders();
HttpBasicAuthentication auth = new HttpBasicAuthentication(this.username, this.password);
headers.setAuthorization(auth);
headers.setAccept(Collections.singletonList(MediaType.APPLICATION_OCTET_STREAM));
Listener<byte[]> imageLoadedListener = new Response.Listener<byte[]>() {
#Override
public void onResponse(byte[] photoByteArray) {
Bitmap bitmap = EfficientImageLoading.decodeBitmapFromByteArray(photoByteArray, viewHolder.thumbnail.getWidth(), viewHolder.thumbnail.getHeight());
viewHolder.thumbnail.setImageBitmap(bitmap);
imageCache.put(item.getThumbnailUrl() + "thumb", bitmap);
//Cache full size and recycle
Bitmap fullBmp = EfficientImageLoading.decodeImageFromByteFullSize(photoByteArray);
imageCache.put(item.getThumbnailUrl(), fullBmp);
}
};
ErrorListener errorListener = new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
viewHolder.thumbnail.setImageResource(R.drawable.ic_launcher);
}
};
this.singleInstance.addToRequestQueue(new CustomImageRequest(Request.Method.GET, item.getThumbnailUrl(), errorListener, headers, imageLoadedListener));
}
Application server logs show:
GET /app//photo/rest/singlephoto/?photoId=7 HTTP/1.1" 406 1067
That is 406-- forbidden or something like that. Also android's LogCat shows an error like the following: BasicNetwork.PerformRequest: Unexpected response code 406 for https://domain/app/singlephoto?photoId=7
Is there something wrong with my controller or my client or both?

Resources