Grails RestBuilder simple POST example - rest

I'm trying to do an OAuth2 user-credentials post to an OAuth2 service using the Grails RestBuilder plugin.
If I try to specify the post body as a map, I get an error about no message converters for LinkedHashMap.
If I try to specify the body as a String, the post goes through, but none of the variables are posted to the server action.
Here's the post:
RestBuilder rest = new RestBuilder()
def resp = rest.post("http://${hostname}/oauth/token") {
auth(clientId, clientSecret)
accept("application/json")
contentType("application/x-www-form-urlencoded")
// This results in a message converter error because it doesn't know how
// to convert a LinkedHashmap
// ["grant_type": "password", "username": username, "password": password]
// This sends the request, but username and password are null on the host
body = ("grant_type=password&username=${username}&password=${password}" as String)
}
def json = resp.json
I've also tried setting the urlVariables in the post() method call, but the username/password are still null.
This is a very simple post, but I can't seem to get it to work. Any advice would be greatly appreciated.

I solved the problem by using a MultiValue map for the body.
RestBuilder rest = new RestBuilder()
MultiValueMap<String, String> form = new LinkedMultiValueMap<String, String>()
form.add("grant_type", "password")
form.add("username", username)
form.add("password", password)
def resp = rest.post("http://${hostname}/oauth/token") {
auth(clientId, clientSecret)
accept("application/json")
contentType("application/x-www-form-urlencoded")
body(form)
}
def json = resp.json

Following code works for Box connection. Spend few of hours figuring this out
String pclient_id = grailsApplication.config.ellucian.box.CLIENT_ID.toString()
String pclient_secret=grailsApplication.config.ellucian.box.CLIENT_SECRET.toString()
String pcode = params.code
log.debug("Retrieving the Box Token using following keys Client ID: ==>"+pclient_id+"<== Secret: ==>"+pclient_secret+"<== Code: ==>"+pcode)
RestBuilder rest = new RestBuilder()
MultiValueMap<String, String> form = new LinkedMultiValueMap<String, String>()
form.add("client_id", pclient_id)
form.add("client_secret", pclient_secret)
form.add("grant_type", "authorization_code")
form.add("code", pcode)
def resp = rest.post("https://app.box.com/api/oauth2/token") {
accept("application/json")
contentType("application/x-www-form-urlencoded")
body(form)
}
def js = resp.json.toString()
println("sss"+js)
def slurper = new JsonSlurper()
def result = slurper.parseText(js)
println("Message:"+result.error)
render js

I found out some very easy to perform such type of action
//Get
public static RestResponse getService(String url) {
RestResponse rResponse = new RestBuilder(proxy:["localhost":8080]).get(Constants.URL+"methodName")
return rResponse
}
//POST : Send complete request as a JSONObject
public static RestResponse postService(String url,def jsonObj) {
RestResponse rResponse = new RestBuilder(proxy:["localhost":8080]).post(url) {
contentType "application/json"
json { jsonRequest = jsonObj }
}
return rResponse
}
Method 1 :
def resp = RestUtils.getService(Constants.URL+"methodName")?.json
render resp as JSON
Method 2 :
JSONObject jsonObject = new JSONObject()
jsonObject.put("params1", params.paramOne)
jsonObject.put("params2", params.paramTwo)
def resp = RestUtils.postService(Constants.URL+"methodName", jsonObject)?.json
render resp as JSON

Related

How to get custom header from response (retrofit & rxjava)

I am trying to get some custom HTTP headers from all the REST API responses in my code.
Here is how I initiate the client:
private fun initializeClient(): OkHttpClient {
val interceptor = HttpLoggingInterceptor()
interceptor.level = HttpLoggingInterceptor.Level.BODY
val httpClient = OkHttpClient.Builder()
.addInterceptor(object : Interceptor {
override fun intercept(chain: Interceptor.Chain): Response {
val original = chain.request()
val request = original.newBuilder()
.header("Content-Type", "application/json")
.method(original.method, original.body)
.build()
return chain.proceed(request)
}
})
.addInterceptor(interceptor)
.build()
return httpClient
}
private fun initializeApi() {
api = Retrofit.Builder()
.baseUrl(API_BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.client(initializeClient())
.build()
.create(RestApi::class.java)
}
Here is a sample of the retrofit implementation:
#POST("/register")
fun registerUser(#Body registerPostData: RegistrationForm): Single<RegistrationResponse>
and the ViewModel part:
disposable.add(
api.registerUser(form)
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribeWith(object : DisposableSingleObserver<Member>() {
override fun onSuccess(value: RegistrationResponse?) {
// no headers in here
response.value = value
}
override fun onError(e: Throwable?) {
}
})
)
The server returns some x-custom-header in all API responses, which I need to capture in all calls.
Thank you!
Change your retrofit class to return a Response:
#POST("/register")
fun registerUser(#Body registerPostData: RegistrationForm): Single<Response<RegistrationResponse>>
then:
override fun onSuccess(result: Response<RegistrationResponse>?) {
// get header from response.headers()
}

Kotlin & Retrofit: Simple POST without Response

I'm trying to do a POST Request with Kotlin and Retrofit where I'm only interested in the statuscode of the request. Tutorials I have seen solve it all a bit different and most of the time they do not compile any more or are very complicated.
Can someone help improving this code:?
interface ClientService {
#POST("user/password-reset")
fun passwortReset(#Query("email") email: String): Observable<Result>
companion object {
fun create(): ClientService {
val retrofit = Retrofit.Builder()
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.baseUrl("https://test-backend.myurl.com/api/")
.build()
return retrofit.create(ClientService::class.java)
}
}
}
I'm not sure how to call it and how to get the statuscode.
Try this example
Under build.gradle:
// retrofit
compile "com.squareup.retrofit2:retrofit:2.3.0"
compile "com.squareup.retrofit2:adapter-rxjava2:2.3.0"
compile "com.squareup.retrofit2:converter-gson:2.3.0"
// rxandroid
compile "io.reactivex.rxjava2:rxandroid:2.0.1"
compile 'com.squareup.okhttp3:logging-interceptor:3.4.1'
compile 'com.squareup.okhttp3:okhttp:3.4.1'
Interface:
interface APIService {
#POST("register")
#FormUrlEncoded
fun registrationPost(#Field("email") email: String,
#Field("password") password: String): Call<Registration>}
//**App Utils**
object ApiUtils {
val BASE_URL = "your_url"
val apiService: APIService
get() = RetrofitClient.getClient(BASE_URL)!!.create(APIService::class.java)
}
Retrofit Client:
object RetrofitClient {
var retrofit: Retrofit? = null
fun getClient(baseUrl: String): Retrofit? {
if (retrofit == null) {
//TODO While release in Google Play Change the Level to NONE
val interceptor = HttpLoggingInterceptor()
interceptor.level = HttpLoggingInterceptor.Level.BODY
val client = OkHttpClient.Builder()
.addInterceptor(interceptor)
.connectTimeout(100, TimeUnit.SECONDS)
.readTimeout(100, TimeUnit.SECONDS)
.build()
retrofit = Retrofit.Builder()
.client(client)
.baseUrl(baseUrl)
.addConverterFactory(GsonConverterFactory.create())
.build()
}
return retrofit
}
}
MainActivity
//Variable declaration
var mAPIService: APIService? = null
//After oncreate
mAPIService = ApiUtils.apiService
//Some Button click
mAPIService!!.registrationPost("SampleTest2#gamil.com", "123456").enqueue(object : Callback<Registration> {
override fun onResponse(call: Call<Registration>, response: Response<Registration>) {
Log.i("", "post submitted to API." + response.body()!!)
if (response.isSuccessful()) {
Log.i("", "post registration to API" + response.body()!!.toString())
Log.i("", "post status to API" + response.body()!!.status)
Log.i("", "post msg to API" + response.body()!!.messages)
}
}
override fun onFailure(call: Call<Registration>, t: Throwable) {
}
})
Inside any function you have to call like:
fun resetPassword(email:String) {
val clientService = ClientService.create(APIConstants
.BASE_URL_WORKSPACE)
addSubscription(apiService.login(APIConstants.API_ACTION_LOGIN, userName, password,
deviceid), object : APICallback<UserLoginResponse>() {
override fun onSuccess(model: UserLoginResponse) {
if (TextUtils.isEmpty(model.errorMessage)) {
mvpView.getDataSuccess(model, apiRequestCode)
} else {
mvpView.getDataFail(model.errorMessage, apiRequestCode)
}
}
override fun onFailure(msg: String?) {
LogUtil.e("Login Failure()- " + msg!!)
}
override fun onFinish() {}
})
}
You will get the success response/result in onSuccess() method.
There is lot's of answers for the same question. Main Funda is to Call Post API using Retrofit.
Let me make some easier things to call Any API.
In this Example of code. i used Demo API from https://jsonplaceholder.typicode.com/
First takes Permission in AndroidManifest.xml
<uses-permission android:name="android.permission.INTERNET" />
Now go create one interface for Post API Response.
interface ApiInterFace {
#POST("users")
fun sendUserData(#Body userPost: UserPost) : Call<UserPost>
}
Now Comes to MainActivity or your Target Activity to call the API.
in this method i used static dummy data for user.
private fun sendDataToApi() {
val retrofitBuilder = Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create())
.baseUrl("https://jsonplaceholder.typicode.com/") // Add Your BaseUrl here
.build()
val jsonPlaceHolder = retrofitBuilder.create(ApiInterFace::class.java)
val userPost = UserPost(1,1,"New Added","Body of the title") // Dummy Data
val call = jsonPlaceHolder.sendUserData(userPost)
call.enqueue(object : Callback<UserPost>{
override fun onResponse(call: Call<UserPost>, response: Response<UserPost>) {
Log.e("TAG", "onResponse: "+response.code() )
}
override fun onFailure(call: Call<UserPost>, t: Throwable) {
Log.e("TAG", "onFailure: "+t.message )
}
} )
}
This is only based on simple example of Post the data to server. There MayBe having changes as per your cases.

Unsupported Grant Type with CustomGrantValidator with IdentityServer 3

I'm trying to set up our IdentityServer solution to accept a custom Grant Validator. Our API project is accessed by to UIs, one that uses Password authentication (which is working) and now one that will use a 3rd party authentication.
In our API I've set up IdentityServer like so:
Startup.cs
public void Configuration(IAppBuilder app)
{
var factory = new IdentityServerServiceFactory()
.UseInMemoryClients(Clients.Get())
.UseInMemoryScopes(Scopes.Get());
var userService = new IdentityUserService();
factory.UserService = new Registration<IUserService>(resolver => userService);
factory.CustomGrantValidators.Add(
new Registration<ICustomGrantValidator, MyGrantValidator>());
var options = new IdentityServerOptions
{
SiteName = "My App Name",
SigningCertificate = Certificate.Get(),
Factory = factory
};
app.Map("/identity", identityServerApp =>
{
identityServerApp.UseIdentityServer(options);
});
}
MyGrantValidator.cs:
public class MyGrantValidator : ICustomGrantValidator
{
public async Task<CustomGrantValidationResult> ValidateAsync(ValidatedTokenRequest request)
{
// For now I just want a basic response. More logic will come later.
var authResult = new AuthenticateResult(
subject: "1234", // user.AccountId.ToString(),
name: "bob" //context.UserName
);
var grantResult = new CustomGrantValidationResult
{
IsError = authResult.IsError,
Error = authResult.ErrorMessage,
ErrorDescription = authResult.ErrorMessage,
Principal = authResult.User
};
return await Task.FromResult(grantResult);
}
public string GrantType => "myGrantType";
}
In my UI, I setup a client like this:
var owinContext = HttpContext.GetOwinContext();
var token = owinContext.Authentication.User.FindFirst(c => c.Type == "myToken")?.Value;
var tokenId = owinContext.Authentication.User.FindFirst(c => c.Type == ClaimTypes.Sid)?.Value;
var client = new TokenClient(
ConfigurationManager.AppSettings["IdentityServerBaseUrl"] + "/connect/token",
"MyUser",
ConfigurationManager.AppSettings["MyClientSecret"],
AuthenticationStyle.Custom
);
var tokenResponse = client.RequestCustomGrantAsync(
"myGrantType",
"read write",
new Dictionary<string, string>
{
{ "token", token },
{ "tokenId", tokenId }
}
).Result;
return Redirect(returnUrl);
When the Request is triggered, I get: unsupported_grant_type
What am I missing?
You're using a client called "MyUser" (weird name for a client, but ok). Is that client registered as one of the in-memory clients with grant type set to "custom"?

Google Vision Rest API in Xamarin

I'm trying to call the Google Vision REST API from a Xamarin.Forms app. I have the following code:-
private async void SendToGoogle(MediaFile file)
{
using (HttpClient client = new HttpClient())
{
string uri = "https://vision.googleapis.com/v1/images:annotate?key=API_KEY";
HttpResponseMessage response;
var stream = file.GetStream();
using (var content = new StreamContent(stream))
{
content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
content.Headers.ContentLength = stream.Length;
response = await client.PostAsync(uri, content);
var resp = await response.Content.ReadAsStringAsync();
}
}
}
But this is returning me a 400 error message:
Invalid JSON payload received. Expected a value.

Use Spring as a REST Client [duplicate]

i have to call this REST service written in scala-akka project from java-spring.
my scala REST service is like
val route =
post {
path("notification" / "signUp"){
headerValueByName("App_Key") { app_key => {
handleWith {
requestParameters: RequestParameters =>
//application specific implementation
}
}
}
}
which contains App_Key and Content-Type in header and request parameters in json format.
request parameters are like:
case class RequestParameters (
var name: String,
var email: String,
var password: String,
var hashKey: String
)
so i have to call this REST service from java spring. I an struggling while calling http://ipadress:port/notification/signUp from java .
U can call this via. Following Implementation :
try {
Client client = Client.create();
WebResource webResource = client.resource(http://ipadress:port/notification/signUp);
JSONObject formData=new JSONObject();
formData.put("name", UserName);
formData.put("email", EmailId);
formData.put("password", Password);
formData.put("urlHash",HashKey);
ClientResponse response = webResource.header("App_Key",xxxxxxxxxxxxxxxxxxxxxxxxxx).type(MediaType.APPLICATION_JSON_TYPE).post(ClientResponse.class, formData);
} catch (Exception e) {
e.printStackTrace();
}