Kotlin Retrofit: Is is possible to replace the Response with a new Response? - kotlin

I have a legacy backend that I can't change, and I'm trying to replace values in the Response body with new values using and Interceptor. I have parsed the body perfectly, and used the NewBuilder() method, but the response object never changes its BufferField value.
My interceptor looks like this:
response.newBuilder()
.code(200)
.protocol(Protocol.HTTP_2)
.message("responseString")
.body(
body.toResponseBody())
.addHeader("content-type", "application/json")
.build()
return response
How is this done?

Related

WinHttpRequest: Send method

I'm trying to pass parameters in the request body, the documentation says :
The request to be sent was defined in a prior call to the Open method. The calling application can provide data to be sent to the server through the Body parameter. If the HTTP verb of the object's Open is "GET", this method sends the request without Body, even if it is provided by the calling application.
So, I need to use POST with body. But when I use use POST with body I have error "Bad Request: message text is empty" and when I use GET with body result is ok. Why?
My code:
WinHttp = NEW COMObject("WinHttp.WinHttpRequest.5.1");
WinHttp.Open("GET", "http://api.telegram.org/botbotname/sendMessage", 0);
WinHttp.setRequestHeader("Content-type", "application/json");
JSONWr = New JSONWriter();
JSONWr.ValidateStructure = False;
JSONParams = New JSONWriterSettings( , Chars.Tab);
JSONWr.SetString(JSONParams);
JSONWr.WriteStartObject();
JSONWr.WritePropertyName("chat_id");
JSONWr.WriteValue(UserId);
JSONWr.WritePropertyName("text");
JSONWr.WriteValue(Text);
JSONWr.WriteEndObject();
JSONString = JSONWr.Close();
WinHttp.Send(JSONString);
work, but how? And why the same with POST doesn`t work?

What's wrong with the API call request

Working on a third part API host. The API call requires a few key/value pairs in the request body with the following example fields:
field1: fieldValue1
field2: fieldValue2
field3: fieldValue3
field4: fieldValue4
The content type should be "application/x-www-form-urlencoded".
When using Postman to make the call, it's always successful. However, when changed to use a simple service to make the call, it's failing. The following is the piece of code that set up the HttpRequestMesage and make the call:
HttpResponseMessage response;
using (var httpClient = new HttpClient())
{
using (var request = new HttpRequestMessage(new HttpMethod("POST"), "https://soem.thirdpartyAPIHost.net"))
{
request.Content = new StringContent("{\"field1\":\"fieldValue1\",\"field2\":\"fieldValue2\",\"field3\":\"fieldValue3\",\"field4\":\"fieldValue4\"}", Encoding.UTF8, "application/x-www-form-urlencoded");
request.Content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/x-www-form-urlencoded");
response = await httpClient.SendAsync(request);
}
}
What's wrong with this implementation?
Found the issue: the content type is Url encoded and therefore the string cannot be in Json format. Instead, the content key/value pairs should be chained together using '&', just like when the parameters are embedded in the Url. So, the sample content in the question should be like this:
request.Content = new StringContent("field1=fieldValue1&field2=fieldValue2&field3=fieldValue3&field4=fieldValue4", Encoding.UTF8, "application/x-www-form-urlencoded");
Please also reference the following: How to send a POST request with Content-Type "application/x-www-form-urlencoded"

How to get the raw response as a String in Spring webflux?

return webClient//
.post()//
.uri(whatever.com)
.header("Authorization", "Bearer " + authToken)//
.header("userId", CLIENT_ID)//
.header("clientRequestId", requestId)//
.bodyValue(bodyValue())//
.retrieve()//
.bodyToMono(Responseclass.class)//
.block();
The above is working. But let's say I'm debugging and I just want to dump the raw response json into a String. How would I do that? toString() after retrieve doesn't work, and bodyToMono(String.class) didn't seem to work either. Either way it just printed the default toString value of the address of the pointer.
With Spring Webflux WebClient you can get response as String like this:
WebClient client = WebClient.create("http://someurl.de/something");
String responseBody = client.get().retrieve().toEntity(String.class)
.block().getBody();
In my German blog I wrote an article about using WebClient, there you will find more details around the code snippet above:
https://agile-coding.blogspot.com/2021/01/reactive-webclient.html

Update response body content using HttpClientFeature

Using a HttpClientFeature implementation with responsePipeline.intercept seems the right way to change an HTTP response.
However, I do not understand how to update the response body. Especially I don't understand how to wrap the new HttpResponse to be passed in to proceedWith.
You can use the HttpResponseContainer to proceed with a new response body:
client.responsePipeline.intercept(HttpResponsePipeline.Transform) { (info, body) ->
val newBody = "test"
proceedWith(HttpResponseContainer(info, newBody))
}

Convert IRestResponse to IRestResponse<T>

I have executed RestRequest and got non-typed IRestResponse.
How can I convert it to IRestResponse<T>?
For example IRestResponse<MyErrorData> or IRestResponse<MyData>?
You need to use the generic overload of Execute:
var client = new RestClient();
client.BaseUrl = BaseUrl;
request.AddParameter("AccountSid", _accountSid, ParameterType.UrlSegment);
var response = client.Execute<T>(request);
Execute<T> is the key to getting back a typed response.
I found that, depending on the version of RestSharp you have installed, Execute<T> threw a compiler error. (Tho it seems fine in v106.15.)
Another option is to cast it, which seems to work when the first option doesn't:
RestClient client = new RestClient();
IRestResponse<T> response = (IRestResponse<T>)client.Execute(request);
Also, don't forget that your method (or class) must be decorated with the T type parameter:
Eg
partial void InterceptResponse<T>(IRestRequest request, ref IRestResponse<T> response)
...
RestClient client = new RestClient();
IRestResponse<T> response = client.Execute<T>(request);
(or IRestResponse<T> response = (IRestResponse<T>)client.Execute(request);)
....
(In this example, I'm intercepting a RestResponse, doing something, such as re-calling, and passing back the new response as ref response.)