API URL Special Character being added in Wordpress - the word "region" becomes "®ion" - url

I have an API working using Javascript code hosted on a Wordpress site. The API works fine, then after a number of requests, the requests begin to fail as the URL has replaced
..."region=uk"....
to
..."®ion=uk"...
If tried URL & HTML encoding it and this works, but then breaks in the same manner with the same issue.
Any idea how to permanently/statically set the word "region" in the API URL?
<script>
var API_URL = 'https://api.example.com/US?sport=NFL&region=US&apiKey=____';
var APIXHR = new XMLHttpRequest();
function btn() {
var url = API_URL;
APIXHR.open('GET', url, true, 'jsonp');
APIXHR.send();
APIXHR.addEventListener("readystatechange", procReq, false);
}
function procReq(e) {
if (APIXHR.readyState == 4 && APIXHR.status == 200) {
var resp = JSON.parse(APIXHR.responseText);
var Home = resp.data.game.TeamA_TeamB.Teams[0];
var Away = resp.data.game.TeamA_TeamB.Teams[1];
document.getElementById("Home").innerHTML = Home;
document.getElementById("Home").style.textTransform = "uppercase";
document.getElementById("Away").innerHTML = Away;
</script>

&reg in HTML is the HTML entity for "®". If you're embedding that code in HTML, you need to escape it according to HTML rules. That means you need ...&region=US&apiKey.... And really every other instance of & needs to be escaped too properly speaking.
An alternative is to put the script into an external file and include it with <script src="...">; there it's not in an HTML context and you can use plain unescaped Javascript.

Related

Customising the index.html file?

I've been messing around with Spring Boot and was pointed at Swagger as a way of documenting my Rest Api.
I managed to get it working except I can't figure out how to customise the index.html file. Whenever I go to http://localhost:8080/index.html it loads the default pet store search bar one and not the one I customised.
I've gone through a tonne of pages online and tried a hundred things but nothing has worked.
Any help would be greatly appreciated.
In my swagger index.html code I have something that looks like this:
$(function () {
var url = window.location.search.match(/url=([^&]+)/);
var pathArray = location.href.split( '/' );
var protocol = pathArray[0];
var host = pathArray[2];
var base = protocol + '//' + host;
if (url && url.length > 1) {
url = url[1];
} else {
url = base + "/api-docs";
}
window.swaggerUi = new SwaggerUi({
url: url,
...
This loads the base, my json code for my swagger api is at /api-docs as you might understand.

OAuth error when exporting Sheet as XLS in Google Apps Script

I had a Google Apps Script to take appointments from my Google Calendar, copy them into a Google Sheet, convert it to XLS and email it. It was working fine until this week.
The initial problem was a 302 error, probably caused by the new version of Sheets. This has been discussed here: Export (or print) with a google script new version of google spreadsheets to pdf file, using pdf options
I got the new location of the file by muting the HTTP exceptions and adjusting the URL accordingly. I also updated the OAuth scope to https://docs.google.com/feeds/ as suggested.
The program is failing with an "OAuth error" message. When muteHttpExceptions is set to true, the message is "Failed to authenticate to service: google".
I guess this is a scope problem but I really can't see what I've done wrong. Naturally, I've tried a few other possibilities without luck.
I've included the code below. Commented code is the instruction that worked until this week.
function getSSAsExcel(ssID)
{
var format = "xls";
//var scope = "https://spreadsheets.google.com/feeds/";
var scope = "https://docs.google.com/feeds/";
var oauthConfig = UrlFetchApp.addOAuthService("google");
oauthConfig.setAccessTokenUrl("https://www.google.com/accounts/OAuthGetAccessToken");
oauthConfig.setRequestTokenUrl("https://www.google.com/accounts/OAuthGetRequestToken?scope=" + scope);
oauthConfig.setAuthorizationUrl("https://www.google.com/accounts/OAuthAuthorizeToken");
oauthConfig.setConsumerKey("anonymous");
oauthConfig.setConsumerSecret("anonymous");
var requestData = {
//"muteHttpExceptions": true,
"method": "GET",
"oAuthServiceName": "google",
"oAuthUseToken": "always"
};
//var url = "https://spreadsheets.google.com/feeds/download/spreadsheets/Export?key=" + ssID
var url = "https://docs.google.com/spreadsheets/d/" + ssID
+ "/feeds/download/spreadsheets/Export?"
+ "&size=A4" + "&portrait=true" +"&fitw=true" + "&exportFormat=" + format;
var result = UrlFetchApp.fetch(url , requestData);
var contents = result.getContent();
return contents;
}
Thanks for your help!
Instead of using OAuthConfig (which must be auth'ed in the Script Editor) you can pass an OAuth2 token instead, retrievable via ScriptApp.getOAuthToken().
The code snippet below uses the Advanced Drive service to get the export URL, but if you hand construct the URL you'll need to ensure that the Drive scope is still requested by your script (simply include a call to DriveApp.getRootFolder() somewhere in your script code).
function exportAsExcel(spreadsheetId) {
var file = Drive.Files.get(spreadsheetId);
var url = file.exportLinks[MimeType.MICROSOFT_EXCEL];
var token = ScriptApp.getOAuthToken();
var response = UrlFetchApp.fetch(url, {
headers: {
'Authorization': 'Bearer ' + token
}
});
return response.getBlob();
}

WIF cannot redirect to a URL containing a hash after federated authentication

I am using WIF and a federated security model using ThinkTecture STS.
When I try to request the url: http://domain.com/#page, WIF is not redirecting to the correct page after authentication.
The ru param in wctx does not contain the correct path of /#path. Instead it ignores the hash and everything after it, so the ru param is just /. A normal url without a hash works fine.
Is there a workout around for this or am I formatting my url incorrectly?Any suggestions?
You can preserve the hash part by emitting JavaScript to perform the redirect, instead of redirecting immediately. The JavaScript code can access the hash part via window.location.hash, and use it to build the ru.
You need to configure the page to allow unauthenticated users (so that WIF passive authentication doesn't kick in). Then you can handle unauthenticated users in the page code.
You can hook the FederatedAuthentication.WSFederationAuthenticationModule.RedirectingToIdentityProvider event in the application start-up code (e.g. Global.asax.cs in Web Forms).
For example (Web Forms):
public class Global : HttpApplication
{
protected void Application_Start(object sender, EventArgs e)
{
FederatedAuthentication.WSFederationAuthenticationModule.RedirectingToIdentityProvider
+= this.RedirectToIdentityProviderViaJavaScript;
}
const string RedirectHtml =
#"<html>
<head>
<script type='text/javascript'>
function authenticate(url, utcTimeString) {{
var ru = window.location.pathname + (window.location.hash || '');
var wctx = 'rm=0&id=passive&ru=' + encodeURIComponent(ru) + '&wtc=' + encodeURIComponent(utcTimeString);
url += '&wctx=' + encodeURIComponent(wctx);
window.location = url;
}}
</script>
</head>
<body onload=""authenticate('{0}', '{1}');"">
</body>
</html>";
private void RedirectToIdentityProviderViaJavaScript(object sender, RedirectingToIdentityProviderEventArgs e)
{
var fam = FederatedAuthentication.WSFederationAuthenticationModule;
var msg = new SignInRequestMessage(new Uri(fam.Issuer), fam.Realm);
var stsUrl = msg.WriteQueryString();
var utcTime = WebPageRoutines.EncodeUtcTimeString(DateTime.Now);
var html = string.Format(RedirectHtml, WebPageRoutines.JavascriptEncode(stsUrl), WebPageRoutines.JavascriptEncode(utcTime));
Response.ClearContent();
Response.Write(html);
Response.Status = "200 OK";
Response.End();
}
}
Be warned that you can't mix ? parameters with # parts with this approach. The ru survives the STS redirection (Thinktecture IdentityServer v2), but WIF seems to mess it up on the final redirect after the POST from the STS.
It will place the ? part after the # part.
http://www.somewebsite.com/page?param=1&other=2#hashbit
Becomes:
http://www.somewebsite.com/page#hashbit?param=1&other=2
Better to use CreateSignInRequest to get all parameters from web.config. Guess it fixes the problem with the querystring to. Example using MVC
const string redirectHtml =
#"<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8'>
<script type='text/javascript'>
function authenticate(url) {{
var ru = window.location.pathname + (window.location.hash || '');
window.location = url.replace('REPLACEWITHURL', encodeURIComponent(ru));
}}
</script>
</head>
<body onload=""authenticate('{0}');"">
</body>
</html>";
var authenticationModule = FederatedAuthentication.WSFederationAuthenticationModule;
var message = authenticationModule.CreateSignInRequest("passive", "REPLACEWITHURL", false);
var stsUrl = message.WriteQueryString();
var html = string.Format(redirectHtml, HttpUtility.JavaScriptStringEncode(stsUrl));
filterContext.Result = new ContentResult { Content = html };
It looks like its the browser that isn't sending the hash part of the url back to the server. I believe this is a HTTP standard, as the hash part was originally only intended for client side anchor tagging.
There are workarounds using ajax/javascript, but as I am using a simple GET request, it would appear impossible.
See these similar questions, which explain the problem...
How to get Url Hash (#) from server side
do browsers remove # in URL automatically?
That's the whole point of hash fragments - that they don't end up on a server.

How to add campaign tracking data to any url automatically?

I get a bunch of different URL from my sources and what I would like is to redirect to the same URL, but with campaign data added to URL (to track the referred clicks).
For example I have these URLs:
www.example.com/category/product/name.html
www.example.com/id_product=5
I want to add at the end the following: utm_source=SOURCE&utm_medium=MEDIUM&utm_campaign=CAMPAIGN
And the URLs to become
www.example.com/category/product/name.html?utm_source=SOURCE&utm_medium=MEDIUM&utm_campaign=CAMPAIGN
www.example.com/id_product=5&utm_source=SOURCE&utm_medium=MEDIUM&utm_campaign=CAMPAIGN
How to I correctly check and cover all the cases if a URL string has parameters, and add mine?
I want to do it in node.js
Thank you
Elaborating on #snkashis, a similar but arguably more elegant solution, again using node's url module, is:
var addQueryParams = function (cleanUrl) {
var obj = url.parse(cleanUrl, true, false);
obj.query['utm_source'] = 'SOURCE';
obj.query['utm_medium'] = 'MEDIUM';
obj.query['utm_campaign'] = 'CAMPAIGN';
delete obj.search; // this makes format compose the search string out of the query object
var trackedUrl = url.format(obj);
return trackedUrl;
};
This works, because url.format first looks for search and, if it can't find it, it composes the query string from the query object
(taken from node url module documentation http://nodejs.org/api/url.html#url_url_format_urlobj )
search will be used in place of query
query (object; see querystring) will only be used if search is absent.
Here is a example showing different scenarios using Node's URL module.
var url = require('url');
var exurls = ["www.example.com/category/product/name.html","www.example.com/id_product=5?hasparam=yes"]
var to_append = "utm_source=SOURCE&utm_medium=MEDIUM&utm_campaign=CAMPAIGN";
for (i=0;i<exurls.length;i++) {
var parsedobj = url.parse(exurls[i],true,false);
//Below checks if param obj is empty.
if (Object.keys(parsedobj.query).length!==0) {
var newpath = parsedobj.href+"&"+to_append;
}
else {
var newpath = parsedobj.href+"?"+to_append;
}
console.log(newpath);
}
Connect will help you:
var connect = require('connect');
var app = connect();
app.use(connect.query());
app.use(function (req, res, next) {
console.log(req.query);
res.end(JSON.stringify(req.query));
});
app.listen(3000);

Use function on Jade output on client side?

I want to parse tweets with this function with content served via Node.js/Express/Jade client side.
String.prototype.parseHashtag = function() {
return this.replace(/[#]+[A-Za-z0-9-_]+/g, function(t) {
var tag = t.replace("#","%23")
return t.link("http://search.twitter.com/search?q="+tag);
});
};
I would like to do it client side so that for example when a new tweet is added that can be parsed to with the same code and displayed directly and not have to go back and forth to the backend and be parsed.
I've made it work with this code, but is there any way to make it simpler, prettier?
!= "<script type='text/javascript'>"
!= "var body = '"
= contents[c].body
!= "';"
!= "document.write(body.parseHashtag());"
!= "</script>"
Yes you can. I will suggest you the following way:
script(type='text/javascript')
var body = contents[c].body;
document.write(body.parseHashtag());
you should also see jade documentation for it:enter link description here

Resources