i can't get the Key (token) by post method when i run the app it shows me an error (500) and the response is null,i tried many times but couldn't find the normal solution.
To be clear i am putting the Hometask and code below:
So the Hometask is :
Create one page Authorization, where there are two fields - Partner Login and Password
Partner account for your testing:
Login: login
Password: password
1) Authorization:
http://client-api.instaforex.com/Home/GetAPIUsageInfo
You need to get token "RequestMoblieCabinetApiToken".
Request URL: http://client-api.instaforex.com/api/Authentication/RequestMoblieCabinetApiToken
Method: POST
Request:
{
"Login": "PARTNER_LOGIN",
"Password": "PARTNER_PASSWORD"
}
In response you get "passkey" (your token).
My code:
ApiInterface
package com.example.instaforexapp.Rest;
import com.example.instaforexapp.Modal.ApiAccount;
import retrofit2.Call;
import retrofit2.http.Body;
import retrofit2.http.Field;
import retrofit2.http.FormUrlEncoded;
import retrofit2.http.POST;
public interface InstaForexApi {
#FormUrlEncoded
#POST("api/Authentication/RequestMoblieCabinetApiToken")
Call<ApiAccount> createAccount( #Field("Login") String login,
#Field("Password") String password);
}
ApiClient
package com.example.instaforexapp.Rest;
import okhttp3.OkHttpClient;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
public class ApiClient {
private static final String BASE_URL = "http://client-api.instaforex.com/";
private static Retrofit retrofit = null;
public static Retrofit getRetrofit() {
HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor();
httpLoggingInterceptor.level(HttpLoggingInterceptor.Level.BODY);
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.addInterceptor(httpLoggingInterceptor)
.build();
if (retrofit == null) {
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.client(okHttpClient)
.build();
}
return retrofit;
}
}
ApiAccount Class
import com.google.gson.annotations.SerializedName;
public class ApiAccount {
#SerializedName("Login")
private String login;
#SerializedName("Password")
private String password;
public ApiAccount(String login, String password) {
this.login = login;
this.password = password;
}
public String getLogin() {
return login;
}
public String getPassword() {
return password;
}
}
MainActivity
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import com.example.instaforexapp.Modal.ApiAccount;
import com.example.instaforexapp.Rest.ApiClient;
import com.example.instaforexapp.Rest.InstaForexApi;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
public class MainActivity extends AppCompatActivity {
private EditText txt_login,txt_password;
private Button btn_confirm;
public static final String TAG = "com.MainActivity";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
txt_login = findViewById(R.id.txt_login);
txt_password = findViewById(R.id.txt_pass);
btn_confirm = findViewById(R.id.btn_confirm);
btn_confirm.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String login = txt_login.getText().toString();
String password= txt_password.getText().toString();
createAccount(login,password);
Log.i(TAG, "login :"+login +" password: "+password);
}
});
}
private void createAccount(String login,String password){
InstaForexApi api = ApiClient.getRetrofit().create(InstaForexApi.class);
Call<ApiAccount> call = api.createAccount(login,password);
call.enqueue(new Callback<ApiAccount>() {
#Override
public void onResponse( Call<ApiAccount> call, Response<ApiAccount> response) {
if (!response.isSuccessful()){
Toast.makeText(MainActivity.this, "Error: "+response.code(),
Toast.LENGTH_SHORT).show();
}
ApiAccount account = response.body();
String toast = null;
if (account != null) {
toast = account.getLogin()+" : " + account.getPassword();
}
Toast.makeText(MainActivity.this, toast, Toast.LENGTH_SHORT).show();
}
#Override
public void onFailure(Call<ApiAccount> call, Throwable t) {
Toast.makeText(MainActivity.this, t.getMessage(),
Toast.LENGTH_SHORT).show();
}
});
}
}
Please help to get the "passkey"
500 status code from server means that your server isn't available at the moment now this issues is not at your end so better communicate with your backend team to resolve this. Check this link to understand about status codes better in server response
Related
I am trying to extend keycloak by creating a new endpoint to authenticate users.
The point is, user is not stored in keycloak, the user is stored in an external system.
The external system will call the new endpoint and provide token (will contains user info), clientId, and clientSecret. and (somehow) we will verify the existence of the user.
The challenge I am facing right now is I cannot create a session for the user. (seems the session requires existed user in keycloak, I am using InMemoryUser)
package com.mhewedy.auth;
import org.jboss.logging.Logger;
import org.jboss.resteasy.spi.HttpRequest;
import org.jboss.resteasy.spi.ResteasyProviderFactory;
import org.keycloak.Config;
import org.keycloak.events.EventBuilder;
import org.keycloak.models.*;
import org.keycloak.protocol.AuthorizationEndpointBase;
import org.keycloak.protocol.oidc.TokenManager;
import org.keycloak.representations.AccessToken;
import org.keycloak.representations.AccessTokenResponse;
import org.keycloak.services.resource.RealmResourceProvider;
import org.keycloak.services.resource.RealmResourceProviderFactory;
import org.keycloak.services.resources.Cors;
import org.keycloak.services.util.DefaultClientSessionContext;
import org.keycloak.storage.adapter.InMemoryUserAdapter;
import javax.ws.rs.*;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.util.UUID;
import static org.keycloak.services.resources.Cors.ACCESS_CONTROL_ALLOW_ORIGIN;
import static org.keycloak.utils.MediaType.APPLICATION_JSON_TYPE;
public class MyEndpoint extends AuthorizationEndpointBase implements RealmResourceProvider {
private final Logger logger = Logger.getLogger(MyEndpoint.class);
private final TokenManager tokenManager = new TokenManager();
public MyEndpoint(RealmModel realm, EventBuilder event) {
super(realm, event);
}
#Override
public Object getResource() {
return this;
}
#Override
public void close() {
}
#GET
#Path("authenticate")
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public Response authenticate(#FormParam("token") String token,
#FormParam("client_id") String clientId,
#FormParam("client_secret") String clientSecret,
#Context HttpRequest request) {
// validate client_id & client_secret
// validate token
logger.info("generating access token...");
String userId = UUID.randomUUID().toString();
UserModel userModel =
new InMemoryUserAdapter(session, session.getContext().getRealm(), userId);
userModel.setUsername(token);
userModel.setEnabled(true);
// this session object doesn't contain the userModel, cause it seems it lookups the user by id and doesn't find it
UserSessionModel userSession = session.sessions().createOfflineUserSession(session.sessions().createUserSession(
session.getContext().getRealm(),
userModel,
token,
"192.168.1.1",
"My",
false,
null,
null
));
ClientModel clientModel = realm.getClientByClientId(clientId);
logger.infof("Configurable token requested for username=%s and client=%s on realm=%s",
userModel.getUsername(), clientModel.getClientId(), realm.getName());
AuthenticatedClientSessionModel clientSession = session.sessions().createClientSession(realm, clientModel, userSession);
ClientSessionContext clientSessionContext =
DefaultClientSessionContext.fromClientSessionScopeParameter(clientSession, session);
AccessToken newToken = tokenManager
.createClientAccessToken(session, realm, clientModel, userModel, userSession, clientSessionContext);
newToken.expiration(10 * 10 * 10 * 10);
EventBuilder eventBuilder = new EventBuilder(realm, session, session.getContext().getConnection());
AccessTokenResponse response = tokenManager
.responseBuilder(realm, clientModel, eventBuilder, session, userSession, clientSessionContext)
.accessToken(newToken)
.build();
return buildCorsResponse(request, response);
}
private Response buildCorsResponse(#Context HttpRequest request, AccessTokenResponse response) {
Cors cors = Cors.add(request)
.auth()
.allowedMethods("POST")
.auth()
.exposedHeaders(Cors.ACCESS_CONTROL_ALLOW_METHODS, ACCESS_CONTROL_ALLOW_ORIGIN)
.allowAllOrigins();
return cors.builder(Response.ok(response).type(APPLICATION_JSON_TYPE)).build();
}
// ----------------------------------------------------------------------------------------------------------------
public static class MyEndpointFactory implements RealmResourceProviderFactory {
#Override
public RealmResourceProvider create(KeycloakSession session) {
KeycloakContext context = session.getContext();
RealmModel realm = context.getRealm();
EventBuilder event = new EventBuilder(realm, session, context.getConnection());
MyEndpoint provider = new MyEndpoint(realm, event);
ResteasyProviderFactory.getInstance().injectProperties(provider);
return provider;
}
#Override
public void init(Config.Scope config) {
}
#Override
public void postInit(KeycloakSessionFactory factory) {
}
#Override
public void close() {
}
#Override
public String getId() {
return "MyEndpoint";
}
}
}
I am using code from here but the use case is differnt.
I solved by saving the user in the cache (db) if not exist:
String username = getUsernameFromToken(token);
String userId = "my-" + username;
UserModel userModel = new InMemoryUserAdapter(session, session.getContext().getRealm(), username);
userModel.setUsername(username);
userModel.setEnabled(true);
if (session.users().getUserById(realm, userId) == null) {
session.userCache().addUser(realm, userId, username, false, false);
}
so I coded this class to Download URLs but it's returning Null Response
I tried to debug but didn't understand anything
package com.example.instaup;
import org.jetbrains.annotations.NotNull;
import java.io.IOException;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
public class Downloader
{
private String myResponse;
public String DownloadText(String url)
{
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(url)
.build();
client.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(#NotNull Call call, #NotNull IOException e) {
e.printStackTrace();
}
#Override
public void onResponse(#NotNull Call call, #NotNull Response response) throws IOException {
if (response.isSuccessful()) {
myResponse = response.body().toString();
}
}
});
return myResponse;
}
}
Can Someone Help me? I'm kinda new to this
You should reuse the client, and use the synchronous form execute instead of the enqueue callback API which returns almost immediately before the request has finished.
import java.io.IOException;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
public class Downloader {
OkHttpClient client = new OkHttpClient();
public String DownloadText(String url) throws IOException {
Request request = new Request.Builder().url(url).build();
try (Response myResponse = client.newCall(request).execute()) {
return myResponse.body().string();
}
}
}
I've just get the code from response, and it says, that my request parameters are wrong, what should my api call look like then?
Here's the hardcoded api call from documenatation
https://api.themoviedb.org/3/discover/movie?api_key=[API_KEY]&with_genres=27
Here's my api call
#GET("3/search/movie")
Call<itemList_model> test(#Query("api_key") String key,#Query("with_genres") int query);
Code
Invalid parameters: Your request parameters are incorrect.
Retrofit call
public void getListViewItems() {
String url = "https://api.themoviedb.org/";
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(url)
.addConverterFactory(GsonConverterFactory.create())
.build();
apiCall api = retrofit.create(apiCall.class);
Call<itemList_model> call = api.test("API_KEY",27); <- 27 stand's for horror genres.
call.enqueue(new Callback<itemList_model>() {
#Override
public void onResponse(Call<itemList_model> call, Response<itemList_model> response) {
if (!response.isSuccessful()) {
Log.i(TAG, "onResponse: " + response.code());
}
Log.i(TAG, "onResponse: "+response.code());
}
#Override
public void onFailure(Call<itemList_model> call, Throwable t) {
Log.i(TAG, "onFailure: " + t.getMessage());
}
});
}
Simple typo. Should be:
https://api.themoviedb.org/3/discover/movie?api_key=[API_KEY]&with_genres=27
But:
https://api.themoviedb.org/3/search/movie?api_key=[API_KEY]&with_genres=27
Working code
package test;
import retrofit2.Call;
import retrofit2.http.GET;
import retrofit2.http.Query;
public interface RetrofitProxy {
#GET("3/discover/movie")
Call<Object> test(#Query("api_key") String apiKey, #Query("with_genres") int genreCode);
}
package test;
import retrofit2.Call;
import retrofit2.Response;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
import java.io.IOException;
public class RetrofitTest {
public static void main(String[] args) throws IOException {
String url = "https://api.themoviedb.org/";
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(url)
.addConverterFactory(GsonConverterFactory.create())
.build();
RetrofitProxy retrofitProxy = retrofit.create(RetrofitProxy.class);
Call<Object> call = retrofitProxy.test("API_KEY", 27);
Response<Object> execute = call.execute();
System.out.println(execute.raw());
System.out.println(execute.isSuccessful());
System.out.println(execute.body());
}
}
I know that with application.yml I can modify the url that call a microservice but my doubt is how can I implement zuul with hystrix circuit braker?, I have a class that extends ZuulFilter and in my run method I'm trying to execute the hystrixCommand like this:
#Override
public Object run() {
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest();
HystrixCommand<String> hystrixCommand = new HystrixCommand<String>(HystrixCommandGroupKey.Factory.asKey(request.getRequestURL().toString())) {
#Override
protected String run() throws Exception {
RestTemplate restTemplate = new RestTemplate();
String responseBody = restTemplate.getForObject(request.getRequestURL().toString(), String.class);
return responseBody;
}
#Override
protected String getFallback() {
return "No response from server";
}
};
String response = hystrixCommand.execute();
RequestContext.getCurrentContext().setResponseBody(response);
return null;
}
But how can I tell hystrixCommand to use the getFallback method if the actual URL failed?, I thought to call the same URL but I think if I do that it will do an infinite cycle or am I not understanding?
Thanks in advance.
UPDATE
This is my whole filter class
package com.filter;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URI;
import javax.servlet.http.HttpServletRequest;
import com.netflix.hystrix.HystrixCommand;
import com.netflix.hystrix.HystrixCommandGroupKey;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.springframework.web.client.RestTemplate;
public class ZuulHttpFilter extends ZuulFilter{
#Override
public String filterType() {
return "pre";
}
#Override
public int filterOrder() {
return 10000;
}
#Override
public boolean shouldFilter() {
return true;
}
#Override
public Object run() {
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest();
HystrixCommand<String> hystrixCommand = new HystrixCommand<String>(HystrixCommandGroupKey.Factory.asKey(request.getRequestURL().toString())) {
#Override
protected String run() throws Exception {
RestTemplate restTemplate = new RestTemplate();
String responseBody = restTemplate.getForObject(request.getRequestURL().toString(), String.class);
return responseBody;
}
#Override
protected String getFallback() {
return "No response from server";
}
};
String response = hystrixCommand.execute();
RequestContext.getCurrentContext().setResponseBody(response);
return null;
}
}
Did you see this question? In fact, the Hystrix javadoc says that it is supposed to execute the fallback automatically:
Returns: R Result of run() execution or a fallback from getFallback()
if the command fails for any reason.
I have restyGWT+GXT project, that send request to server project (Spring Boot), so, my restyGWT+GXT part:
buiid.gradle:
...
compile 'org.fusesource.restygwt:restygwt:2.0.3'
compile 'javax.ws.rs:jsr311-api:1.1.1'
my rest service in restyGWT+GXT part:
import org.fusesource.restygwt.client.MethodCallback;
import org.fusesource.restygwt.client.RestService;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import java.util.List;
public interface LoadHelloService extends RestService {
#GET
#Path("/rest/loadHelloService")
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public void loadHelloService(MethodCallback<List<Hello>> callback);
}
bean Hello.java:
public class Hello {
private final String id;
private final String name;
#JsonCreator
public Hello(#JsonProperty("id") String id, #JsonProperty("name") String name) {
this.id = id;
this.name = name;
}
public String getId() {
return id;
}
public String getName() {
return name;
}
}
in MainMenuPage (implements IsWidget):
on click menuButton1 send request to server project (Spring Boot):
#UiHandler("menuButton1")
void selectOnMenu1(SelectEvent event) {
...
restServerLoader.loadHelloListFromServer();
}
so, RestServerLoader class with method loadHelloListFromServer:
import com.google.gwt.core.client.GWT;
import com.sencha.gxt.widget.core.client.box.MessageBox;
import org.fusesource.restygwt.client.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class RestServerLoader {
public void loadHelloListFromServer() {
String pageBaseUrl = "http://127.0.0.1:8080/";
Defaults.setServiceRoot(pageBaseUrl);
Map<String, String> headers = new HashMap<>();
headers.put("Access-Control-Allow-Methods", "GET");
Resource resource = new Resource(Defaults.getServiceRoot(), headers);
LoadHelloService service = GWT.create(LoadHelloService.class);
((RestServiceProxy)service).setResource(resource);
service.loadHelloService(new MethodCallback<List<Hello>>() {
public void onSuccess(Method method, List<Hello> response) {
MessageBox messageBox = new MessageBox("response (list) = " + response.toString());
messageBox.show();
//code your stuff here
}
public void onFailure(Method method, Throwable exception) {
MessageBox messageBox = new MessageBox("exception = " + exception);
messageBox.show();
//code your stuff here
}
});
}
}
So, and when I send request loadHelloService I have: org.fusesource.restygwt.client.FailedStatusCodeException: status code 0.
:(((((((
my server part (Spring Boot) rest:
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.*;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.util.ArrayList;
import java.util.List;
#Path("/")
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public class HelloResource {
#Context
private HttpServletResponse response;
#OPTIONS
#Path("loadHelloService") //The response for the preflight request made implicitly by the bowser
public Response loadHelloPreflight() {
Response response = Response.ok()
.header("Access-Control-Allow-Origin", "*")
.header("Access-Control-Allow-Methods", "POST, GET, UPDATE, OPTIONS")
.header("Access-Control-Allow-Headers", "*")
.header("Access-Control-Max-Age", "18000").build();
return response;
}
#GET
#Path("loadHelloService")
public List<Hello> loadHelloList() {
response.addHeader("Access-Control-Allow-Origin", "*");
response.addHeader("Access-Control-Allow-Methods", "POST, GET, UPDATE, OPTIONS");
response.addHeader("Access-Control-Allow-Headers", "*");
List<Hello> list = new ArrayList<>();
list.add(new Hello("1", "ronan"));
list.add(new Hello("2", "john"));
return list;
}
}
so, When I send request, I input method loadHelloPreflight, but when send request to loadHelloList I have: org.fusesource.restygwt.client.FailedStatusCodeException: status code 0., Why??? :((, When I send request to server part (Spring Boot) from browser Postman Client - all good!, I get list of hellos, but I want do it from restyGWT+GXT part :((( Help me, please.
Did you forget some cors headers like below ?
.header("Access-Control-Allow-Headers", "x-http-method-override");