Azure Event Hub Authorization from Android - java

I‘m working on an application that sends data to an azure event hub. This is similar to the blog post here:http://sreesharp.com/send-events-from-android-app-to-microsoft-azure-event-hubs/
However, I updated the connection code to use OkHttp:
public void sendMessageOkHttp(String dataPacket, String connectionString, String sasKey){
// Instantiate the OkHttp Client
OkHttpClient client = new OkHttpClient();
// Create the body of the message to be send
RequestBody formBody = new FormBody.Builder()
.add("message", dataPacket)
.build();
// Now create the request and post it
Request request = new Request.Builder()
.header("Authorization", sasKey)
.url(connectionString)
.post(formBody)
.build();
Log.i(TAG,"about to send message");
// Now try to send the message
try {
Log.i(TAG,"sending message....");
Response response = client.newCall(request).execute();
Log.i(TAG,"message sent");
Log.i("Azure Response",String.valueOf(response.message()));
// Do something with the response.
} catch (IOException e) {
e.printStackTrace();
}
}
However this returns a response from the event hub "Unauthorized". The sas key I am using is for a shared access policy that I created with send and listen permissions. It is the primary key.
What am I doing wrong here? The Azure documentation doesnt really help me in this case because it focused on using the Azure Java libraries that are not Android compatible (i.e. they require Java 1.8)

It's not the SAS Key you send in the Authorization header, it's the SAS Token. Here are like 5 or six different languages for generating the SAS Token from the key: https://learn.microsoft.com/en-us/azure/service-bus-messaging/service-bus-sas-overview

Related

Accessing Individual SSE Payloads in Response using Java

We are currently using Apache HttpClient (5) to send a POST request to a server. The response is sent back to us using server side events (SSE) with multiple payloads using the standard format:
data: {...}
Currently we have code like this which sends the request and receives the response:
// Set the socket timeout
final ConnectionConfig connConfig = ConnectionConfig.custom()
.setSocketTimeout(socketTimeout, TimeUnit.MILLISECONDS)
.build();
// Custom config
final BasicHttpClientConnectionManager cm = new BasicHttpClientConnectionManager();
cm.setConnectionConfig(connConfig);
// Build the client
try (final CloseableHttpClient client = HttpClientBuilder.create().setConnectionManager(cm).build()) {
// Execute the request
return client.execute(request.getRequest(),
// Get and process the response
response -> HttpResponse.builder()
.withCode(response.getCode())
.withContent(EntityUtils.toByteArray(response.getEntity()))
.build()
);
}
This all works great except I need to access the individual incoming response payloads (data {...}) in the response as they arrive instead of waiting for them all to finish before being able to access the response.
If this isn't possible using Apache I am open to other options providing they can send a normal HTTP(S) POST.
Ok I couldn't get it to work with the Apache Client but I did find this video that showed how to do it using the native HttpClient.
// Create the client
final HttpClient client = HttpClient.newHttpClient();
// Make the request
final HttpResponse<Stream<String>> response = client.send(request, HttpResponse.BodyHandlers.ofLines());
// Status code check
if (response.statusCode() != 200) ...;
// This will consume individual events as they arrive
response.body().forEach(System.out::println);

SparkJava GET Handler Returning NULL After Serialization of Long

I'm trying to write a simple server with SparkJava but I am having considerable difficulty serialize a long using Gson and transmitting the JSON to an OkHttp client program inside a GET handler. The server returns NULL, more specifically response.body.string() is
<html><body><h2>404 Not found</h2></body></html>
Any ideas on what the issue could be? thanks.
Here is the GET handler:
get("routingEngine/getDefaultRoute/distance", (request,response) ->{
response.type("application/json");
long distance = 100;
return gson.toJson(distance);
});
Here is the client code making the simple request (please disregard the parameters (requestParameters) being passed in along with the request, they just provide information to an irrelevant before filter):
// build url
HttpUrl url = new HttpUrl.Builder()
.scheme("http")
.host("127.0.0.1")
.port(4567)
.addPathSegment("routingEngine")
.addPathSegment("getDefaultRoute")
.addPathSegment("distance")
.build();
// build request
Request getDefaultRouteDistanceRequest = new Request.Builder()
.url(url)
.post(RequestBody.create(JSON,gson.toJson(requestParameters)))
.build();
// send request
Call getDefaultRouteDistanceCall = httpClient.newCall(getDefaultRouteDistanceRequest);
Response getDefaultRouteDistanceResponse = getDefaultRouteDistanceCall.execute();
// parse response
// testing
System.out.println(getDefaultRouteDistanceResponse.body().string());
The last line leads to the following output
<html><body><h2>404 Not found</h2></body></html>
The endpoint you created was a GET endpoint and the call being made is for POST.

How to send x-www-form request on java?

Above is what im trying to send
In java this is what I have
RequestBody formBody = new FormBody.Builder()
.add("param1", "abc")
.add("param2", "abc")
.add("param3", "abc")
.build();
Request request = new Request.Builder()
.url("http://localhost:3001/addsomething")
.post(formBody)
.build();
doesn't seem to work. I have OkHttpClient but I'm not sure how to use it to send the above result
What are you confused about? I'm a little unsure. I did a little research but it seems the only thing you're missing is a client, and then sending the request you've created and receive a response back.
To create a client, look at the most updated documentation on OkHttpClient, but this is what I found:
OkHttpClient client = new OkHttpClient();
And then send your request using that client using:
Response response = client.newCall(request).execute();
Then you can proceed to do something with that response.
All you have to understand is that you're creating a request (essentially asking the server for some information). Depending on your request, you'll get a response back (as in above), which you can then use to get whatever you're looking for.

Java - HTTPS Basic authentification with Apache httpclient

I am trying to get some data (json data -> restful server) from a HTTPS server with basic authentification using the Apache httpclient. The SSL certificate is selfsigned.
The server is responding very well to a browser call and also when using curl.
However using the java Apache httpclient, that's another story.
Client side :
The basic authentification is working : the server sends me 401 errors if forget the authorization header or if I set the wrong base64 encoded login:password.
The https/SSL part is working : I am successfully getting data from online restful json server but sadly no way to find an online restful json server with basic authentification for testing purpose...
try {
CloseableHttpClient httpClient = null;
try {
httpClient = HttpClients.custom()
.setSSLSocketFactory(new SSLConnectionSocketFactory(SSLContexts.custom()
.loadTrustMaterial(null, new TrustSelfSignedStrategy())
.build()
)
)
.setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)
.build();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (KeyManagementException e) {
e.printStackTrace();
} catch (KeyStoreException e) {
e.printStackTrace();
}
HttpGet getRequest = new HttpGet("https://localhost:5050/getdata");
getRequest.addHeader("Accept", "*/*");
getRequest.addHeader("Authorization", "Basic UBJ0aHVyOmFo0XElYHU=");
HttpResponse response = httpClient.execute(getRequest);
Debugging is telling me :
Caused by: org.apache.http.ProtocolException: The server failed to respond with a valid HTTP response
True! It's not a valid HTTP response that I would like to get, it's a valid HTTPS response!
I guess that I am missing something...
Solved!
The error was from the server side : my response did not include any headers....
httpclient seems to like well made responses from a server. That's not true for a browser or for curl : garbage they can receive , display they will !

failure : retrofit.RetrofitError: 307 Temporary Redirect?

I am using the library com.squareup.retrofit:retrofit:1.9.0, in order to send data to my server from my android Application.
In fact,when I want to send a request to the server, I found this error:
failure : retrofit.RetrofitError: 307 Temporary Redirect
I try many idea but the same problem persist.
Please Expert help me to resolve this issue.
Regards
Edit: if you must not use Retrofit 1.9, switching to a newer version (ie 2.0+) should handle the solution covered below automatically.
Looks like your HTTP client (on Android side) should handle this redirection by reading the Location value in the response header you are receiving when this happens, which supposed to contain a target redirection URL you ought to hit from the client again.
See their comment here.
So for now you need to implement this at the application level (which
is hard with Retrofit 1, easier with the forthcoming Retrofit 2) or
wait until OkHttp 3.1(ish) when we implement the newest spec.
See also what 307 means.
Fixing 307 errors - general The 307 response from the Web server
should always include an alternative URL to which redirection should
occur. If it does, a Web browser will immediately retry the
alternative URL. So you never actually see a 307 error in a Web
browser, unless perhaps you have a corrupt redirection chain e.g. URL
A redirects to URL B which in turn redirects back to URL A. If your
client is not a Web browser, it should behave in the same way as a Web
browser i.e. immediately retry the alternative URL.
If the Web server does not return an alternative URL with the 307
response, then either the Web server sofware itself is defective or
the Webmaster has not set up the URL redirection correctly.
See javadoc for Retrofit 1.9.0 to grab the Location header value(URL) from response;
http://static.javadoc.io/com.squareup.retrofit/retrofit/1.9.0/retrofit/client/Response.html#getHeaders--
// omitting null check for brevity
for (Header header : response.getHeaders())
{
if (header.getName().equals("Location")) {
redirectURL = header.getValue();
}
}
// do a redirect to redirectURL
I got the solution after a lot of efforts. May be this will help you. If you are getting this error "203 HTTP 307 Temporary Redirect" then this trick will help you.
Append '/' to your web service at the end and then check this error goes away. I don't know the reason behind this but it works for me.
For me, my old request web service: https://mydomain/rest/Search.
Using this URL I was getting "203 HTTP 307 Temporary Redirect" where I was able to get a response in POSTMAN and web browser.
My new request web service with the trick: https://mydomain/rest/Search/.
This '/' resolve the issue.
You are Using Old dependency
Change your dependency from
"com.squareup.retrofit:retrofit:1.9.0"
to
compile 'com.squareup.retrofit2:retrofit:2.2.0'
compile 'com.squareup.retrofit2:converter-gson:2.2.0'
compile 'com.squareup.okhttp3:okhttp:3.4.1'
also add this dependency to get full log
compile 'com.squareup.okhttp3:logging-interceptor:3.4.1'.
Add this method in your Retrofit Client Class
HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
logging.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
httpClient.connectTimeout("Your_Time", TimeUnit.SECONDS);
httpClient.readTimeout("Your_Time", TimeUnit.SECONDS);
httpClient.addInterceptor(logging);
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("BASE URL")
.addConverterFactory(GsonConverterFactory.create())
.client(httpClient.build())
.build();
Below code is to Handle the Http protocol Exception
public Response post(String url, String content) throws IOException {
RequestBody body = RequestBody.create(PROTOCOL, content);
Request.Builder requestBuilder = new Request.Builder().url(url).post(body);
Request request = requestBuilder.build();
Response response = this.client.newCall(request).execute();
if(response.code() == 307) {
String location = response.header("Location");
return post(location, content);
}
return response;
}
If you want to handle all 307 responses, you can create and add an Interceptor to do the job; This interceptor simply creates a new request with the new path which is indicated in the response header "location".
val client = OkHttpClient.Builder()
.addInterceptor {
val request = it.request()
val response = it.proceed(request)
if (response.code() == 307) {
val url = HttpUrl.Builder()
.scheme(request.url().scheme())
.host(request.url().host())
.addPathSegment(response.header("location", request.url().url().path)?: "")
.build()
val newRequest = Request.Builder()
.method(request.method(), request.body())
.url(url)
.headers(request.headers())
.build()
return#addInterceptor it.proceed(newRequest)
}
response
}
.build()
Retrofit.Builder().client(client).build()
Solution 1
You can create an extra interceptor to handle 307
private static class RedirectInterceptor implements Interceptor {
#Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
Response response = chain.proceed(chain.request());
if (response.code() == 307) {
request = request.newBuilder()
.url(response.header("Location"))
.build();
response = chain.proceed(request);
}
return response;
}
}
and add the RedirectInterceptor to your okHttpClient(okhttp2 for example)
OkHttpClient okHttpClient = new OkHttpClient();
okHttpClient.interceptors().add(new RedirectInterceptor());
okHttpClient.setFollowRedirects(false);
Solution 2
You can create an ApacheClient with LaxRedirectStrategy
private ApacheClient createRedirectClient(){
return new ApacheClient(HttpClients.custom()
.setRedirectStrategy(new LaxRedirectStrategy()).build());
}
RestAdapter.Builder builder = new RestAdapter.Builder()
.setEndpoint("http://yourendpoint")
.setClient(createRedirectClient());
.setLogLevel(RestAdapter.LogLevel.FULL)
.build();
Try to put HttpLoggingInterceptor and check the logs. Also cross check with Rest Client if your server is returning back with proper response or not for provided input along with parameters.
For HttpLoggingInterceptor, this is the following way to configure
public RestClient() {
HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
logging.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
httpClient.addInterceptor(logging);
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("BASEURL")
.addConverterFactory(GsonConverterFactory.create())
.client(httpClient.build())
.build();
//APIInterface initiation
service = retrofit.create(APIInterface.class);
}
Below are the dependencies for the same
compile 'com.squareup.retrofit2:converter-gson:2.1.0'
compile 'com.squareup.okhttp3:logging-interceptor:3.3.1'
compile 'com.squareup.retrofit2:retrofit:2.1.0'
Go through this Sample tutorial of Retrofit, if you are following some other possibilities of initiating the rest client

Categories