Yii2 HttpClient: Access Request instance from Response instance - yii2

Using yii2-httpclient, what is the correct way to access the corresponding yii\httpclient\Request instance from the resulting yii\httpclient\Response object?
I am trying to write a custom XML parser which needs to know what URL it is parsing. It does not seem to be possible to access the original Request (through which I could get the URL) from a parser instance (only the Response).
I have considered utilizing yii\httpclient\Client::EVENT_AFTER_SEND to copy the request into a variable, but that would not be thread-safe, so I need a better solution.

If your parser needs to know URL of request to parse response, it is probably not a parser and you're overusing parser API and ParserInterface. I suggest to create some component which will wrap and hide all request-response-parser logic. Then you will be able to implement custom parser and call it manually:
public function get($url) {
$client = new Client();
$response = $client->createRequest()
->setUrl($url)
->send();
return (new MyParser($url, $response))->getContent();
}

Related

How to sanitize html/javascript from request.JSON in grails 3.1.10 restful service

We have a grails 3.1.10 restful service that takes in json data on the http post. This data can contain html/javascript which is not desired.
Using encodeAsHTML and the xss-sanitizer plugin XssSanitizerUtil.stripXSS methods I can see how to sanitize an individual string, but how can I push this to a higher scope through filters or something so that when request.JSON is used in the controller it has already been sanitized?
Or is there already another easier way to accomplish this?
I created an interceptor to apply to the appropriate controllers. In it I made a copy of the JSON parse(HttpServletRequest request) method. Near the end of the method where it parses the inputStream I plugged in my Sanitizer class that uses xss-sanitizer:
def body = IOUtils.toString(pushbackInputStream, encoding)
def sanitized = Sanitizer.sanitize(body)
json = JSON.parse(sanitized);

Microsoft.Net.Http vs Microsoft.AspNet.WebApi.Client

I need to access REST service from .NET application and it seems it can be done with any of those two packages. It's not clear to me which package is supposed to be used in which scenarios. Can anyone bring more light into this?
The short answer is yes, use Microsoft.AspNet.WebApi.Client.
https://www.nuget.org/packages/Microsoft.AspNet.WebApi.Client/
This package adds support for formatting and content negotiation to
System.Net.Http. It includes support for JSON, XML, and form URL
encoded data.
Microsoft.AspNet.WebApi.Client actually depends on Microsoft.Net.Http, and extends the HttpClient with some more features that you would likely need to talk to a RESTful service such as ASP.NET Web API (e.g. JSON and XML support).
Both packages operate in the System.Net.Http namespace and revolve around the key HttpClient class.
The Microsoft.AspNet.WebApi.Client package contains the System.Net.Http.Formatting.dll assembly, which adds some handy extension methods to HttpClient and HttpContent (and others).
So for example:
using (var client = new HttpClient())
{
var response = await client.GetAsync("http://localhost/foo/api/products/1");
response.EnsureSuccessStatusCode();
var product = await response.Content.ReadAsAsync<ProductInfo>();
}
The ReadAsAsync method is an extension method that Microsoft.AspNet.WebApi.Client adds onto the HttpContent object. This automatically figures out if the response is JSON, XML or form URL encoded (the aforementioned content negotiation), and then uses the corresponding formatter to de-serialize it into your strongly typed model (in this case, ProductInfo).
If you tried to just use Microsoft.Net.Http, the ReadAsAsync method wouldn't be available to you, and you'd only be able to read the content as raw data such as bytes or string, and have to do the serializing / de-serializing yourself.
You also get extension methods to PUT / POST back to the service in JSON or XML without having to do that yourself:
// Save the ProductInfo model back to the API service
await client.PutAsJsonAsync("http://localhost/foo/api/products/1", product);
Key Microsoft.AspNet.WebApi.Client extensions:
https://msdn.microsoft.com/en-US/library/system.net.http.httpclientextensions.aspx
https://msdn.microsoft.com/en-US/library/system.net.http.httpcontentextensions.aspx

Other technologies that can perform DTO request response like WCF

I have a WCF service that allows me make a request using an DTO and replies with a DTO for a WPF application. For example I pass a filter object for products which has a few properties for things I want to filter on and a couple of extras for paging, (the server will take care processing the filter object and getting the data) an example is like this.
public async Task<ObservableCollection<ProductListItem>> GetProductList(ProductFilter filter, int startIndex, int pageSize, string sortBy)
I am wondering if there exists any other technologies beside WCF that allow such an operation, From my preliminary research which may be quite off is that WebAPI uses the GET, POST, PUT verbs and routing rules which is quite different.
ServiceStack looks like it might be able to do this I can see on slide 37 at https://servicestack.net/features
it says.
List<Product> productOver2Bucks = client.Get(new FindProducts{PriceGreaterThan = 2})
Which seems pretty close but might still require Rest verbs as it uses a Get().
I don't know it it is FUD or not but I have been reading that soap over WCF is believed by some to be a legacy technology and JSON is the way of the future. So is there a replacement technology that will work with a method signature to the one I have above? That i could call from platforms such as Windows universal applications.
In ServiceStack if you design your Service with the Any method name, e.g
public object Any(Request request)
{
return new Response { ... };
}
This will allow calling this Service from Any HTTP Verb on any Format or endpoint (e.g. JSON, XML, MsgPack, Protocol Buffers, SOAP, Message Queue's, etc).
Also you don't need to define any [Route] for your Request DTO's since it will automatically fallback into using the pre-defined Routes when none are available.
public class Request : IReturn<Response> { ... }
public class Response { }
So with the above Service you can use ServiceStack .NET ServiceClients to call the API's using any verb, e.g:
var client = new JsonServiceClient(baseUrl);
Response response = client.Get(new Request { ... });
Response response = client.Post(new Request { ... });
When preferred you can also use the async API's, e.g:
var response = await client.GetAsync(new Request { ... });
var response = await client.PostAsync(new Request { ... });
Which if you don't care for using verbs you can use the generic Send API, e.g:
Response response = client.Send(new Request { ... });
Which just uses POST underneath, although it's highly recommended to use Get for "read only" queries as it will allow the Services HTTP responses to be cached by any intermediate HTTP Middleware or proxies.
Add ServiceStack Reference
Also if you're coming from WCF you'll also enjoy ServiceStack's, Add ServiceStack Reference which provides a number of advantages over WCF's Add Service Reference feature but still provides the same utility in being able to generate a typed API from a remote url for:
C# Add Reference
F# Add Reference
VB.NET Add Reference
TypeScript Add Reference
With more languages to follow.
Advantages over SOAP
Whilst ServiceStack still enables WSDL's, XSD's for your Services so they can be called from SOAP 1.1/1.2 endpoints for legacy compatible reasons - there are a number of reasons why using clean HTTP and JSON/XML API's are preferred.

Laravel return json or view

I'm developing an API where if the user specifies the action with .json as a suffix (e.g. admin/users.json), they get the response in the return of json, otherwise they get a regular html View.
Some actions may not have a json response, in which case they would just return a html View.
Does anyone have advice on how this can be implemented cleanly? I was hoping it could be achieved via the routing.
I suggest you to create your application as an api.
Foreach page, you need two controllers. Each controller use a different route (in your case, one route ending by .json, and one without).
The json controller return data in json form. The "normal" controller call the corresponding json route, deserialize the json, then pass the resulting array to the view.
This way, you've got a standardized api (and maintained, because your own app use it) available, as well as a "normal" website.
More information:
Consuming my own Laravel API
Edit: Maybe it's doable with a filter, but I'm not sure about that and I don't have time to try it myself right now.
In Laravel 5.x, to implement both capabilities like sending data for AJAX or JSON request and otherwise returning view template for others, all you have to do is check $request->ajax() or $request->isJson().
public function controllerMethod(Request $request)
{
if ($request->ajax() || $request->isJson()) {
//Get data from your Model or whatever
return $data;
} else {
return view('myView.index');
}
}

GWT RequestBuilder POST JSON application/json

I'm trying to send JSON data to a server.
RequestBuilder builder = new RequestBuilder(RequestBuilder.POST, url);
builder.setHeader("Content-Type", "application/json");
builder.setRequestData(getJSONString());
builder.setCallback(myCallbackObject);
builder.send();
I do this in eclipse and I saw in the TCP/IP Monitor that my JSON Data is not transmitted as post in the request. If I ask for
builder.getRequestData();
I can see the JSON data is right there.
What do I need for the data to get on the server?
You might be running into the browser's same-origin policy if the url that you are attempting to connect to is not from the same origin as your GWT nocache.js file. Is your callback's onFailure() being called? Also, see if Request.getSatusCode() returns 0, which is indicative of SOP problems.
To simply post JSON data with HTTP post, you can use GWT Overlay Types to define a post method using JQuery. A possible snapshot:
public static native void post(String json) /*-{
var data = JSON.parse(json);
$wnd.$.post(url, data);
}-*/;
I don't know if it is necessary to add JQuery to your HTML. I did, and worked. You can do this by adding the following line to your .html file:
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Then, you can simply call that method in your java code:
post(json);
(: