RestTemplate encoding parameter with + - encoding

I've been struggling to properly encode a parameter like this:
filter=startDate eq "2020-08-21T00:00:00+04:30"
So it's encoded like this:
filter=startDate%20eq%20%222020-08-21T00:00:00%2B04:30%22
But I get this:
filter=startDate%20eq%20%222020-08-21T00:00:00+4:30%22
Which obviously is wrong, I need the + sign encoded as well.
The code looks like this.
UriComponentsBuilder builder;
URI uri;
uri = UriComponentsBuilder.fromUriString(uri).build(id);
builder = UriComponentsBuilder.fromUri(uri);
if (filter != null) {
builder.queryParam("filter", filter);
}
builder.build(false).toUriString();
The full URL should look like this:
https://example.com/object/id?filter=startDate%20eq%20%222020-08-21T00:00:00%2B04:30%22
Tried this solution without luck: RestTemplate.exchange() does not encode '+'?
Any idea?
Update:
Saw this promising answer https://stackoverflow.com/a/56291853/198108 but can't seem to make it work. I tried to add it like this in my class that extends OAuth2RestTemplate:
HttpClient httpClient =
CustomHttpClientBuilder.create().setMaxConnTotal(5_000).setMaxConnPerRoute(2_500).build();
// Allow to log the response body and also return it to the caller.
setRequestFactory(
new BufferingClientHttpRequestFactory(
new HttpComponentsClientHttpRequestFactory(httpClient)));
But the code is never executed.

Related

Mask Headers in spring restdocs

So I was trying to follow this example:
Spring REST Docs: how to replace parameters
What I'm trying to do is to mask the JWT token in the header of my request and I have an OperationPreprocessor that looks like this:
import org.springframework.http.HttpHeaders
import org.springframework.restdocs.operation.OperationRequest
import org.springframework.restdocs.operation.OperationRequestFactory
import org.springframework.restdocs.operation.OperationResponse
import org.springframework.restdocs.operation.preprocess.OperationPreprocessor
class AuthHeaderPreprocessor implements OperationPreprocessor {
#Override
OperationRequest preprocess(OperationRequest request) {
HttpHeaders headers = new HttpHeaders()
headers.putAll(request.getHeaders())
headers.set('Authorization', 'Bearer 12345')
return new OperationRequestFactory().create(
request.getUri(),
request.getMethod(),
request.getContent(),
headers,
request.getParameters(),
request.getParts()
)
}
#Override
OperationResponse preprocess(OperationResponse response) {
return response
}
}
When I run the test they run without error but I don't see any change to the header. I'm using the OperationPreprocessor like this
RestAssuredRestDocumentation.document(
'event-list', preprocessRequest(new AuthHeaderPreprocessor()), ...
Any ideas what I may be missing.
The code I had actually worked and is a good example of how to filter headers. For some reason when testing it initially I wasn't working, but that seems like it was maybe just something cached in the build not getting cleared, as it works now.

How to parse an object variable in eventChannel callback method?

I am programming a flutter app, in which I have a callback from the native system containing some nfc information. I register the callback via the following line of code:
eventChannel.receiveBroadcastStream().listen(_onEvent, onError: _onError);
The callback looks like this:
void _onEvent(Object event) {
//Receive Event
print("NFC Event received");
//Get the Payload
event['Payload']; //This does not work, it gives an error
}
But how can I parse out the data? I know it contains a field by the name Payload however, I cannot access it via event['Payload'].
I am very confused, I tried to cast it to another type like this: Map<String, String> eventMap = Map<String, String>.from(event); but that didnt work. Could someone please point out what I am doing wrong and how I can correctly extract the data?
Without too much information of native part, I suggest
you can reference this package or fork this https://github.com/akeblom/flutter-nfc-reader
directly
this repo fix some issue of pub.dev and work well in real device
the dart code you need reside in
https://github.com/akeblom/flutter-nfc-reader/blob/master/lib/flutter_nfc_reader.dart
void _onEvent(dynamic data) {
print("Event");
print(data);
}
Edit add more detail
akeblom has add Write NFC capability to IOS, so IOS part should work. please ue this fork https://github.com/akeblom/flutter-nfc-reader
For IOS MissingPluginException issue, I do not have IOS, I suggest you can ask akeblom
The data part you mentioned in comments if I do not misunderstand is line 77, please see describe below
In Android part.
https://github.com/akeblom/flutter-nfc-reader/blob/master/android/src/main/kotlin/it/matteocrippa/flutternfcreader/FlutterNfcReaderPlugin.kt
line 174, use kotlin mapOf returns a new read-only map with the specified contents and eventSink.success result to Dart
if (message != null) {
val data = mapOf(kId to id, kContent to message, kError to "", kStatus to "read")
eventSink?.success(data)
}
In https://github.com/akeblom/flutter-nfc-reader/blob/master/lib/flutter_nfc_reader.dart
line 22, with named constructor
factory NfcData.fromMap(Map data) {
NfcData result = NfcData(
id: data['nfcId'],
content: data['nfcContent'],
error: data['nfcError'],
statusMapper: data['nfcStatus'],
);
In line 77, NFC read start and _onEvent(dynamic data) get the data.
stream use this named constructor, and parse data, here with map((result)) transfer to NfcData
static Stream<NfcData> get read {
final resultStream = _channel
.invokeMethod('NfcRead')
.asStream()
.asyncExpand((_) => stream
.receiveBroadcastStream()
.map((result) => NfcData.fromMap(result)));
return resultStream;
In https://github.com/akeblom/flutter-nfc-reader/blob/master/example/lib/main.dart
line 33, response has transfered to NfCData, so example just use _nfcData = response;
FlutterNfcReader.read.listen((response) {
setState(() {
_nfcData = response;
});
});
The simplest way I found to parse an event to a Map is the following:
I encoded the variable to a String (but I use json.encode(event)instead of event.toString()as encode(event)returns a valid string.
Then I use this string to construct a map via json.decode. All of this is achieved with the flutter native library dart:convert. The complete code looks like this:
import 'dart:convert';
...
void _onEvent(dynamic event) {
//Receive Event
print("NFC Event received");
String str = json.encode(event);
Map eventMap = json.decode(str);
}
Have you tried event.toString()? It might return a string containing the field you are trying to get, from which you can easily parse the value.
You may also want to try:
Class<?> clazz = event.getClass();
Field payload= clazz.getField("Payload"); //Note, this can throw an exception if the field doesn't exist.
String fieldValue = payload.toString();
If it isn't returning what you want, you may need to make an interface for the object type, with a get method, or override the toString method to get return the Payload value.

Vibe.d REST Interface serve image

Sending a bunch of binary back to the user like an image:
interface API
{
#path("/data/image")
#contentType("image/png")
ubyte[] getImagePreview(string foo);
}
The function is returning a Json array with the values of the ubyte[]
Here are the list of attributes I can use:
adjustMethodStyle
bodyParam
contentType
extractHTTPMethodAndName
headerParam
method
noRoute
path
queryParam
rootPathFromName
Source: Vibe.d site
The only attribute that can do the job is contentType and it's said there that it only works with ubyte[] functions, and that's what I used.
What am I missing?
You can try hunt framework so easy use:
#Action
Response image(string imageName)
{
return new FileResponse("/data/image/" ~ imageName);
}
More read wiki:
https://github.com/huntlabs/hunt-framework/wiki/FileResponse

Angular 4, URLSearchParams, standard QueryEncoder and equal sign with x-www-form-urlencoded POSTs

using URLSearchParams in a POSt body generally works in Angular.
However, I've just noticed that is I try to post the equal character in a string, the QueryEncoder doesn't encode it and leaves it there as a '=' sign so the right part of the string is cut on the server.
I've checked the standard QueryEncoder and I've seen the = replacement is done on purpose, so I've created my own QueryEncoder to fix the issue.
However, I'm not sure this is a good approach and I've noticed that using URLSearchParams as form body is suggested in many places.
Is there a better and safer way to do it? I feel like Angular should provide at least a standard "FormQueryEncoder" for this use case or clearly discourage the usage.
Edit: adding some code example:
This is the simplified version of the problem:
let formParams = new URLSearchParams();
formParams.set('longDescription', 'This = That');
let requestOptions: RequestOptionsArgs = new RequestOptions({
method: RequestMethod.Put,
headers: headers,
body: formParams,
search: queryParameters
});
this.http.request(path, requestOptions);
On the server side, it was sending the '=' not encoded so I was only getting the string This as longDescription value.
To fix it, I've created a custom QueryEncoder:
export class FormQueryEncoder {
encodeKey(k: string): string { return encodeURIComponent(k); }
encodeValue(v: string): string { return encodeURIComponent(v); }
}
And I've used it with the URLSearchParams I'm using as body:
let formParams = new URLSearchParams('', new FormQueryEncoder());
Dem

Send two params in GET request

I'm pretty new using vertx framework, and in the documentation I cannot see the silly thing about how to send two parameters in a GET request. So far I tried this.
$.getJSON('/user/'+ attributeName + ":"+value, function (data) {
userListData = data;
$.each(data, function () {
$('#userInfoName').text(data.fullname);
$('#userInfoAge').text(data.age);
$('#userInfoGender').text(data.gender);
$('#userInfoLocation').text(data.location);
});
});
And then in server side
router.get("/user/:attributeName:value").handler(routingContext -> {
JsonObject query = new JsonObject();
query.put(routingContext.request().getParam("attributeName"), routingContext.request().getParam("value"));
But then I can see how attributeName not only gets the value of the first param but part of the second, very weird.
You're probably doing it wrong. You can get it as a single param and later split with ":" or have two parameters defined in the url as... /:attribname/:value/...
Both will handle your requirement