Change ServiceStack default format to JSON, but keep HTML format for SwaggerUI - json

Essentially, I want all of my responses returned in JSON by default, searched for an answer and stumbled upon this discussion: ServiceStack default format
What I tried:
Setting DefaultContentType to JSON and disabling Feature.Html --> works for responses, but breaks SwaggerUI (error on page render)
Only setting DefaultContentType to JSON --> doesn't break SwaggerUI, but making requests to my services from browser returns HTML (which makes sense because browsers usually the Accept header to receive html or xml, but I want to default to JSON)
That said, is there any way to only (and safely) enable Feature.Html for SwaggerUI? Maybe using PreRequestFilters?

The issue is removing the HTML Format essentially removes HTML ContentType from consideration, but I've changed it to preserve the Content Type if the Service returns a raw HTML string in this commit where the Swagger UI can return HTML pages even if the HTML Format is disabled.
This change is available from v5.4.1 that's now available on MyGet.
An alternative is to leave the HTML Format enabled but use a request filter to change the Content Type to JSON where it's HTML for all Requests you want to do this for, e.g:
PreRequestFilters.Add((req, res) => {
if (req.ResponseContentType.Matches(MimeTypes.Html) && !req.PathInfo.StartsWith("/swagger-ui"))
req.ResponseContentType = MimeTypes.Json;
});

Related

How to make react prevent browsers caching externally loaded html?

I'm using dangerouslySetInnerHTML method to load a dynamic html from server. The issue I'm running into is, the file is getting cached and reloading the file doesn't show the changes made to it.
Is there any react method beside using <meta> tag to prevent caching only the loaded html?
A simple way to solve this is to add a parameter to the URL you are fetching the html from. Something like:
const data = fetch('https://example.com/myapi/foobar?' + Date.now(), {...});
or with template literals if you prefer:
const data = fetch(`https://example.com/myapi/foobar?${Date.now()}`, {...});
This will concatenate the current unix timestamp to your url effectively making it always unique which will prevent browsers from caching it.

Scrapy can't find form on page

I'm trying to write a spider that will automatically log in to this website. However, when I try using scrapy.FormRequest.from_response in the shell I get the error:
No <form> element found in <200 https://www.athletic.net/account/login/?ReturnUrl=%2Fdefault.aspx>
I can definitely see the form when I inspect element on the site, but it just did not show up in Scrapy when I tried finding it using response.xpath() either. Is it possible for the form content to be hidden from my spider somehow? If so, how do I fix it?
The form is created using Javascript, it's not part of the static HTML source code. Scrapy does not parse Javascript, thus it cannot be found.
The relevant part of the static HTML (where they inject the form using Javascript) is:
<div ng-controller="AppCtrl as appC" class="m-auto pt-3 pb-5 container" style="max-width: 425px;">
<section ui-view></section>
</div>
To find issues like this, I would either:
compare the source code from "View Source Code" and "Inspect" to each other
browse the web page with a browser without Javascript (when I develop scrapers I usually have one browser with Javascript for research and documentations and another one for checking web pages without Javascript)
In this case, you have to manually create your FormRequest for this web page. I was not able to spot any form of CSRF protection on their form, so it might be as simple as:
FormRequest(url='https://www.athletic.net/account/auth.ashx',
formdata={"e": "foo#example.com", "pw": "secret"})
However, I think you cannot use formdata, but instead they expect you to send JSON. Not sure if FormRequest can handle this, I guess you just want to use a standard Request.
Since they heavily use Javascript on their front end, you cannot use the source code of the page to find these parameters either. Instead, I used the developer console of my browser and checked the request/response that happened when I tried to login with invalid credentials.
This gave me:
General:
Request URL: https://www.athletic.net/account/auth.ashx
[...]
Request Payload:
{e: "foo#example.com", pw: "secret"}
Scrapy has a JsonRequest class to help with posting JSON. See here [https://docs.scrapy.org/en/latest/topics/request-response.html]
So something like the below should work
data = {"password": "pword", "username": "user"}
# JSON POST to API login URL
return JsonRequest(
url=url,
callback=self.after_login,
data=data,
)

Is there a built in way to parse an incomplete xml-text in Javascript in the latest Firefox?

I have read the answers so far, that DOMParser can't handle incomplete (and because of that not well formed) XML-Data.
As all major browsers can handle faulty html-source I just wonder if it's possible to use a workaround to get the browser interpreting the not well formed XML-Data.
For example by putting a manually written DOCTYPE-tag with an ATTLIST at the start of the Data, and then telling the browser to interpret it in a hidden frame, and then using the resulting dom-tree?
Is there a built in way to parse an incomplete xml-text in Javascript in the latest Firefox?
or
How would the DOCTYPE and ADDLIST have to look like, if in the Data there are unknown tags like <mytag> with attributes like nr="..." and date="..."? and <anothertag>with attributes like nr="..." and upto="..."?
Just use a DOMParser.
function parseFragment(fragment) {
var parser = new DOMParser(),
doc = parser.parseFromString(fragment, "text/html");
return doc.getElementsByTagName("body")[0];
}
and
var root = parseFragment('<foo><bar some="thing"><baz></bar>');
console.log(root.getElementsByTagName("bar")[0].getAttribute("some"));
// -> "thing"

Restfullyii prepending <link> tag to the json response

Hi I'm new to restfulyii
I'm having a problem with the json response a tag is being prepended
Refer to the code below
(just assume that there are '<>' for the link tag)
<link rel="stylesheet" type="text/css" href="/assets/e5ba1689/srbac.css" />{"success":true,"message":"Record(s) Found","data":{"totalCount":1,"share":[{"id":"0","elementid":"1","type":"video","suid":"1","duid":"5","permissions":"superuser"}]}}
this coming from api/ under GET method and same with other rest verbs
I can't parse my JSON data because of the prepended line.
Please help..
reference:
localhost/api/ - method: GET/POST/PUT/DELETE
Everything is working fine with restful yii except that json response format...
Thanks in advance!
Ohmel Paguirigan
The problem seams to be that YII is not recognizing that your request is an actual Ajax request.
Search in srbac/components/Helper.php for:
if (!Yii::app()->request->isAjaxRequest){
Yii::app()->clientScript->registerCssFile($cssFile);
}
You will notice that SRBAC is checking if your request is an actual Ajax request.
Yoshi on the Yii Forms says that:
yii checks if there is a X-Requested-With HTTP header set (which
should result in an $_SERVER['HTTP_X_REQUESTED_WITH'] server variable)
and whether it contains the string 'XMLHttpRequest'. But this is a
custom header set by most javascript libraries (and so does jQuery).
There are e.g. some proxies which drop these custom headers (mainly
for security reasons) and therefore your application can't recognize
whether it's an ajax request or not. It's not 100% reliable.
Therefore, you must make sure that your javascript library is injecting this Header.
To do this in Javascript, in your app.run
add the following:
$http.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
Then, all of y our http requests in angular will send the header yii needs to discern that an AjaxRequest is being sent!
Hope this helps!

ASP.Net MVC page refresh using json values instead of html

I have a page that has a "prev" and "next" day button, and rather than reload the entire page, I simply do an ajax call to a controller that returns the entire partial view, which I replace the div with.
$("#divId").html(ajaxResponse);
Pretty simple.
However, I'm finding that this partial view is vastly more data than I need (html doesn't change at all, just the data) and it's causing slowness on mobile browsers.
My question is, is there a tool out there that will let me return a JSON representation of the model data and refresh all the values on the page automatically?
For example, say I have:
#Html.InputFor(x => x.FirstName)
and the JSON returns
{ FirstName: 'Henry', LastName: 'McLeery' }
Is there a library available that can automate the process of doing:
$("#FirstName").val(ajaxResponse.FirstName);
$("#LastName").val(ajaxResponse.LastName);
etc...
?
Take a look at Angular.js. Angular is a JavaScript framework which uses the mvc pattern.
After binding UI elements to your model the displayed data changes automatically when updating your model. Angular offers a nice api to consume ajax requests with json data.
Look at this:
Get and update json using angular.js