I'm working on a Azure Functions App and i have some issues with the routes, when I add a matching rule with * inside, it doesn't work anymore. Anyone have an idea of what I'm doing wrong ?
When I uncomment one of the other rules or just change the route of Test Route from /{code} to /{*code}, it fails and gives me the Bad Request response.
My routing file proxies.json
{
"$schema": "http://json.schemastore.org/proxies",
"proxies": {
"Test Route": {
"matchCondition": {
"route": "/{code}"
},
"backendUri": "https://%WEBSITE_HOSTNAME%/api/UrlTester/{code}"
}
//,
//"Let's Encrypt Support" : {
// "matchCondition": {
// "route": "/.well-known/acme-challenge/{*code}"
// },
// "backendUri": "https://%WEBSITE_HOSTNAME%/api/LetsEncrypt/{code}"
//},
//"Domain Redirect": {
// "matchCondition": {
// "route": "/{*shortUrl}"
// },
// "backendUri": "http://%WEBSITE_HOSTNAME%/api/UrlRedirect/{shortUrl}"
//},
//"Api": {
// "matchCondition": {
// "route": "/api/{*path}"
// },
// "backendUri": "http://%WEBSITE_HOSTNAME%/api/{path}"
//}
}
}
I'm using this following fork: https://github.com/duijvelshoff/serverless-url-shortener
And this documentation: https://learn.microsoft.com/en-us/azure/azure-functions/functions-proxies
Thanks.
As per this github issue a catchall {* route redirecting to the same function app will cause a 400 response.
Moving your HTTP triggered functions to a separate function app, and changing the backend URLs will fix your issues.
try something like "route": "id={code}"
Related
I've been trying to fetch some url using Devtools 'copy as fetch' but I can see no response. If I try replay xhr, it will work. It's strange since it doesn't work for this particular site, but if I try 'copy as fetch' on some others it does bring a result.
What I'm trying to do is grab the response body and display it some other way (it's a schedling software, and I'm trying to modify the way it displays the calendar view since it displays everything together).
I have an extension that enables me to modify XMLHttpRequest so I can get the response of any XHR, but since the first async executes before I inject the script, then I'm always missing the first one.
I plan on using chrome webRequest to stop the first one and fetch it again.
manifest.json
{
"name": "jobber",
"version": "2.0",
"description": "Build an Extension!",
"manifest_version": 2,
"permissions": [
"webNavigation",
"webRequest",
"*://secure.name.com/*"
],
"content_scripts": [{
"matches": ["*://secure.name.com/calendar*"],
"js": ["contents.js"],
"run-at": "document_start"
}],
"externally_connectable": {
"matches": ["*://secure.name.com/calendar*"]
},
"background": {
"scripts": ["background.js"]
}
}
contents.js
(function () {
'use strict';
let s = document.createElement("script");
s.textContent = overloadXHR();
document.head.insertBefore(s, document.head.children[0]);
s = document.createElement("script");
s.textContent = displayCalendar;
document.head.insertBefore(s, document.head.children[0]);
})();
function overloadXHR() {
const text = `
console.log(\`overriding: \${Date.now()}\`);
const rawOpen = XMLHttpRequest.prototype.open;
let json = [];
(function(){
XMLHttpRequest.prototype.open = function () {
this.addEventListener("readystatechange", e => {
if (/secure.name.com.calendar.*?calendar=true/i.test(this.responseURL)) {
if ((this.status == 200) && (this.readyState == 4)) {
console.log(this.readyState);
try {
json = JSON.parse(this.response);
window.setTimeout(() => (window.displayCalendar({json}))({json}), 1000);
}
catch (e) { console.log(e); }
}
}
});
rawOpen.apply(this, arguments);
}
}())
`;
return text;
}
function displayCalendar({ json }) {
// do something
}
I tried POST requests too. I could see that they would work, but no response given tho.
original request:
copy as fetch
copy as fetch response
copy as fetch timing
With the help of the forum I was able to get my httpclient observable mapping issue sorted with this syntax;
this._http.get<DomainMetaData>(serviceURL);
which works great! However, I have a json response coming back from the server which is nested and wonder if I can use the same syntax as I'm currently using or if I need to now manually .map the response into my classes?
Based on posts I've seen here on SO I've created two classes to represent the nested structure of the response JSON (see below).
The function call...
getDomainMetaData(domain): Observable<DomainMetaData> {
let serviceURL = "http://localhost:3000/selectdomains?domain=" + domain;
return this._http.get<DomainMetaData>(serviceURL);
}
The classes...
export class DomainMetaDataAttr {
constructor(public name: string,
public value: string) {
}
}
export class DomainMetaData {
constructor(public name: string,
public attributes: DomainMetaDataAttr[]) {
}
}
An example of the json...
//DomainMetaData
// {
// "ResponseMetadata": {
// "RequestId": "11f000bf-0dff-8a2a-31ff-8631a9f25b5b",
// "BoxUsage": "0.0008183545"
// },
// "Items": [
// {
// "Name": "2",
// "Attributes": [
// {
// "Name": "Document Date",
// "Value": "22/03/13"
// },
// {
// "Name": "Document Ref",
// "Value": "Doc test"
// }
// ]
// },
I love the neatness and simplicity of my current solution but I appreciate I may now have to change my code!
Many Thanks.
If I understand correctly you want to know how to use the JSON response from an HttpClient call.
I currently approach it like this:
// x.service.ts
getData() {
return this.http.get(URL);
}
// x.component.ts
this.service.getData().subscribe(res => {
if (res['data']) {
const data = res['data'];
// do whatever with the data
}
});
With the above approach you can run whatever methods / filters you want on the JSON e.g. map over the array and pull data out / mutate it, etc. Not sure if it's necessary to create additional classes to deal with the nested JSON data.
Oops! The code I posted actually works, I just wasn't referencing the results in the attributes array correctly.
Thanks for taking the time to look at this.
chrome.webRequest.onBeforeRequest.addListener(function (details) {
if (details.method === "POST") {
var bodyObj = details['requestBody'];
// I can see/modify bodyObj.formData, but
}
}, {
urls: ["<all_urls>"]
}, [
"blocking", "requestBody"
]););
How can I return a modified formData?
I see from Chrome Extensions's documentation that I can cancel a request, redirect a request, or modify the request headers, but how can I change the formData?
Based on http://crbug.com/91191, it looks like there's only read-only access to POST data for webRequest's onBeforeRequest listeners.
It means we can see what is being sent in a request BODY like this below:
chrome.webRequest.onBeforeRequest.addListener(function (details) {
console.log(details['requestBody']);
}, {
urls: ["<all_urls>"]
}, [
"blocking", "requestBody"
]);
But we can't update it for now.
In the beginning I thought that the problem is with chrome.runtime.sendMessage() I was sending two messages. One for accessing localstorage and another one to get/read the file data, but nothing changed after I merged them in one sendMessage which means that the actual problem is window.webkitRequestFileSystem() it's returning the previous file instead of the current one.
Is there a better/faster way of storing something client side ? (I'm willing to try everything) ?
manifest.json
{
"manifest_version": 2,
...
"content_scripts": [
{
"matches": ["http://*/*", "https://*/*"],
"js": ["content.js"],
"run_at": "document_end"
}
],
"background": {
"scripts": ["background.js"]
},
"permissions": [
"unlimitedStorage"
]
}
background.js
var theme = '';
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
if(request.method == "getTheme") {
themes = JSON.parse(localStorage["themes"]);
themeName = "";
for (var i = themes.length - 1; i >= 0; i--) {
if(request.url.indexOf(themes[i]) !== -1) {
themeName = themes[i];
}
};
window.webkitRequestFileSystem(window.PERSISTENT, 0, readFromFileStorage.bind(window, themeName), errorHandler);
sendResponse({data: theme});
}
});
function readFromFileStorage(filename, fs) {
fs.root.getFile(filename, {}, function(fileEntry) {
fileEntry.file(function(file) {
var reader = new FileReader();
reader.onloadend = function(e) {
theme = this.result;
};
reader.readAsText(file);
}, errorHandler);
}, errorHandler);
}
function errorHandler(e) {
console.log('Error: ' + e.message);
}
content.js
chrome.runtime.sendMessage({method: "getTheme", url: location.href}, function(response) {
console.log(response.data);
});
As your question is not an SSCCE it is hard to test it, but I think your problem is understanding of JS asynchronous nature.
So how your code will actually execute:
First window.webkitRequestFileSystem(PERSISTENT, 0, successCallback, errorHandler); will be executed
Then sendResponse({data: theme}); will send the response with whatever is stored in theme
Then either successCallback either errorHandler will be called depending on file request success. If successCallback will be called then you'll have your theme variable filled with the value you want. But it will be to late as you already sent the response.
The next time you pass the message you will receive previous theme value (point 2) as your code will find new value only after you'll send the value.
A solution may be to call sendResponse inside of successCallback after you find your desired value (you'll have to pass sendResponse into readFromFileStorage). If you'll do so then you may consider to add sendResponse into errorHandler function just to be sure that your code will always get a valid response.
In case that you'll move the sendResponse into a callback then you have to return true from addListener function, otherwise on addListener return channel will be closed and response will not be sent.
The icanhaz documentation uses this as an example as how to pull ich templates from a remote server.
$.getJSON('/myserver/templates.json', function (templates) {
$.each(templates, function (template) {
ich.addTemplate(template.name, template.template);
});
});
However, the documentation doesn't really tell you what the file on the remote server has to look like. Anyone have any ideas?
Your templates JSON object may look like this:
{
"templates": {"name": "optionTemplate",
"template": "{{#options}}<option value='{{value}}'>{{display}}</option>{{/options}}"
}
}
This will define a template for options in a select box.
You can add the template using the code you specified (actually I tweaked it slightly as I couldn't get it to work as specified):
$.getJSON('templates.json', function (templates) {
$.each(templates, function () {
ich.addTemplate(this.name, this.template);
});
});
//now call getJSON on your input data
$.getJSON('options.json', function (data) {
var optionElements = ich.optionTemplate(data);
$('#selectBox').append(optionElements);
}
For clarity, here is what options.json contains:
{
"options": [
{ "value": "optionValue",
"display": "optionDisplay"
},
{ "value": "optionValue2",
"display": "optionDisplay2"
}]
}
Do let me know how you get on :)