Azure Functions: NodeJS - HTTP Response Renders as XML rather than HTML - node.js

I have a node azure function with the function.json like this:
{
"disabled": false,
"bindings": [
{
"name": "req",
"type": "httpTrigger",
"direction": "in",
"methods": [ "get" ]
},
{
"name": "res",
"type": "http",
"direction": "out"
}
]
}
I want the function to return html to give me a page like this:
However, when I write the index.js like this:
module.exports = function (context, sentimentTable) {
context.res = {
body: "<!DOCTYPE html> <html> <head> </head> <body> Hello World </body> </html>",
contentType: "text/html"
};
context.done();
};
I am getting this:
Can Azure Functions return html?

Must be 'Content-Type' and you specify headers this way
context.res = {
body: '...',
headers: {
'Content-Type': 'text/html; charset=utf-8'
}
}
See this blog post on AzureServerless.com - http://azureserverless.com/2016/11/12/a-html-nanoserver/

Alternatively, you can use the fluent express style:
module.exports = function (context, req) {
context.res
.type("text/html")
.set("someHeader", "someValue")
.send("<!DOCTYPE html> <html> <head> </head> <body> Hello World </body> </html>");
};
Make sure that the http output binding is set to res and not $return.

Related

Problem with CORS in Nest.js app after deployment on Vercel

POST request in my Nest.js app not working after deployment on Vercel and I receive CORS error, but cors in my app is enable and when I send GET request all working. When I test my request in postman all working. I am not sure but maybe this error can happen through that I use React Query or problem with vercel and I not right deployment my app.
I receive such error:
Access to XMLHttpRequest at 'https://server-store.vercel.app/api/auth/login' from origin 'https://next-store-liard-three.vercel.app' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
And I enabled CORS such method:
app.enableCors({
origin: ['http://localhost:3000', 'https://next-store-liard-three.vercel.app'],
allowedHeaders: ['Accept', 'Content-Type'],
methods: 'GET,HEAD,PUT,PATCH,POST,DELETE,OPTIONS',
preflightContinue: false,
optionsSuccessStatus: 204,
credentials: true,
});
This is my file vercel.json:
{
"version": 2,
"name": "next-store-server",
"buildCommand": "npm start",
"installCommand": "npm install",
"builds": [
{
"src": "dist/main.js",
"use": "#vercel/node"
}
],
"routes": [
{
"src": "/(.*)",
"dest": "dist/main.js",
"methods": ["GET", "POST", "PATCH", "PUT", "DELETE"]
}
]
}
Also I try enable CORS other way, but it is not help me.
I try enable CORS, such method:
const app = await NestFactory.create(AppModule, { cors: true });
On client I using Next.js, reactQuery and axios for sending request
import axios from "axios";
import { FAuth, IUser } from "./Auth.types";
const AuthService = {
async registration(dto: IUser) {
const { data } = await axios.post<FAuth>(
`${process.env.NEXT_PUBLIC_SERVER_API_URL}/api/auth/registration`,
dto,
);
return data;
},
async login(dto: IUser) {
const { data } = await axios.post<FAuth>(`${process.env.NEXT_PUBLIC_SERVER_API_URL}/api/auth/login`, dto);
return data;
},
};
This my custom useMutation hooks
export const useRegistration = () =>
useMutation((dto: Omit<IUser, "_id">) => AuthService.registration(dto), {
onSuccess: () => {
toast.success("Success", {
theme: "colored",
});
},
onError: (data: any) => {
toast.error(data.response.data.message, {
theme: "colored",
});
},
});
export const useLogin = () =>
useMutation((dto: Omit<IUser, "_id">) => AuthService.login(dto), {
onSuccess: () => {
toast.success("Success", {
theme: "colored",
});
},
onError: (data: any) => {
toast.error(data.response.data.message, {
theme: "colored",
});
},
});
Try to add "OPTIONS" into methods, this worked for me
vercel.json:
{
"version": 2,
"builds": [{ "src": "src/main.ts", "use": "#vercel/node" }],
"routes": [
{
"src": "/(.*)",
"dest": "src/main.ts",
"methods": ["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"]
}
]
}

Chrome Extension - not sending cookies in the request

I've read tons of questions on SO, tried multiple things but to no luck. My question would be similar, but I'm posting because I've tried everything but still not succeeded.
I want to check whether there's a user session maintained at my server. I've a webservice which returns a boolean value, based on the cookies received.
It's the responsibility of the browser to send cookies (if any) while requesting the server. So, when I request via the chrome-extension, theoretically the browser should send along the cookies too. However, it does not.
Here's my code:-
content.js
fetch('https://zoffers.in/apis/shops/get_aff_url/', {
credentials: 'include',
mode: 'cors',
async: false,
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
name: 'Hubot',
login: 'hubot',
})
})
.then(function(data) {
})
.catch(function(error) {
})
Manifest.json
{
"manifest_version": 2,
"version": "0.1",
"content_scripts": [{
"matches": [
"https://*/*/"
],
"js": ["js/content.js"],
"run_at": "document_start"
}],
"browser_action": {
// "default_icon": "icon.png",
"default_popup": "popup.html",
"default_title": "Click here!"
},
"permissions": [
"identity",
"identity.email",
"tabs",
"notifications",
"cookies",
"https://zoffers.in/"
]
}
What wrong am I doing? Can anyone please help me through it.
UPDATED
content.js
message = {
'event_type': 'Event1',
}
chrome.runtime.sendMessage(message);
background.js
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse){
if(request.event_type === 'Event1'){
chrome.tabs.query({active: true, currentWindow: true}, function(tabs){
fetch('https://zoffers.in/apis/shops/get_aff_url/', {
credentials: 'include',
mode: 'cors',
async: false,
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
name: 'Hubot',
login: 'hubot',
})
})
.then(function(data) {
})
.catch(function(error) {
})
}
}
}
);
Have added background.js to manifest.json file. But still not working.
You can use standard Cookies api and access cookies for any URL that is available.
You might need to set the SameSite attribute of the cookies to None.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite
You may also have to set your browser to accept third-party cookies.

How to log cookies from a cookie jar?

How can I log cookies that are stored in a cookie jar using the request-promise npm module.
I have tried printing the cookie jar variable but as expected that does not work.
How I am creating the jar,
var request = require('request-promise');
var sess = request.jar()
The code sending the request,
request({url: myurl, jar: sess}, function () {
request(
{
url: 'myurl',
method: 'POST',
headers: [
{
"Accept": "application/json",
}
],
postData: {
"xqr":"1"
}
}
)
I expect all the cookies used to send my request to be printed out using console.log()
request uses tough-cookie internally. So you can easily access to tough-cookie store which is an abstract class and use its prototype function getAllCookies.
function logCookies(jar){
jar._jar.store.getAllCookies(function(err, cookieArray) {
if(err) throw new Error("Failed to get cookies");
console.log(JSON.stringify(cookieArray, null, 4));
});
}
And this will log all cookies and its properties.
[
{
"key": "1P_JAR",
"value": "1P_JAR_VALUE",
"expires": "2019-01-23T20:09:38.000Z",
"domain": "google.com",
"path": "/",
"hostOnly": false,
"creation": "2018-12-24T20:09:37.800Z",
"lastAccessed": "2018-12-24T20:09:38.097Z"
},
{
"key": "NID",
"value": "NID_VALUE",
"expires": "2019-06-25T20:09:38.000Z",
"domain": "google.com",
"path": "/",
"httpOnly": true,
"hostOnly": false,
"creation": "2018-12-24T20:09:37.802Z",
"lastAccessed": "2018-12-24T20:09:38.098Z"
}
]
If you only want to get raw cookie string you can just simply use
console.log(cookieArray.map(cookie => cookie.toString()))
And it will give you
[
'1P_JAR=1P_JAR_VALUE; Expires=Wed, 23 Jan 2019 20:15:02 GMT; Domain=google.com; Path=/',
'NID=NID_VALUE; Expires=Tue, 25 Jun 2019 20:15:02 GMT; Domain=google.com; Path=/; HttpOnly'
]

PWA deployed in node.js running in Standalone mode on Android and iOS

I am trying to implement PWA in standalone mode on Android and iOS.
I have a secure node.js server (HTTPS) and everything is apparently working fine (index.html, manifest.json, serviceWorker.js, ...).
The application runs correctly from Chrome and can be added to the home screen and run in standalone mode on the PC. It also works in standalone mode on iOS (Safari), but not on Android (Chrome).
Because of this, I tested three different PWAs: with a basic example of ionicPWA, another example of angularPWA, and then with an own PWA. The behavior is the same, if I deploy applications on a server like Firebase, then the apps work in standalone mode on both iOS and Android. But if I deploy the apps on my node.js server, the application only works in standalone mode on iOS but not on Android.
I have tested on different Android devices with the v67.0.3396.87 of Chrome, on Android 8.1.0, 7.0.0 and 6.0.0. The PWA only opens in browser mode.
I have seen other questions and answers about this behavior (ref1, ref2, ref3) but I have not found the solution.
Could this be a bug of Chrome-v67? Or can it be some configuration of my server that affects the behavior of Chrome on Android?
Any ideas?
UPDATE1: index.html, manifest.json, seviceWorker (sw.js) and audit with Chrome devTools
index.html (head)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!--title-->
<title>PWA Test</title>
<!--icon-->
<link rel="shortcut icon" type="image/png" href="img/favicon.png"></link>
<!--color-->
<meta name="theme-color" content="#FB314E">
<!--for mobile-->
<meta name="MobileOptimized" content="width">
<meta name="HandheldFriendly" content="true">
<!--for Apple devices-->
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<link rel="apple-touch-icon" href="img/favicon.png"></link>
<link rel="apple-touch-startup-image" href="img/favicon.png"></link>
<!-- pwa configuration-->
<link rel="manifest" href="manifest.json"></link>
<!--style-->
<link rel="stylesheet" href="css/styles.css"></link>
<!--jQuery-->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<!--Scripts-->
<script src="main.js"></script>
</head>
manifest.json
{
"name": "PWA 3002 Test",
"short_name": "PWA 3002",
"description": "PWA aplication",
"background_color": "#FFF",
"theme_color": "#FB314E",
"orientation": "portrait",
"display": "standalone",
"start_url": "./index.html?utm_source=web_app_manifest",
"scope": "./",
"lang": "es-ES",
"icons": [
{
"src": "./img/favicon-1024.png",
"sizes": "1024x1024",
"type": "image/png"
},
{
"src": "./img/favicon-512.png",
"sizes": "512x512",
"type": "image/png"
},
{
"src": "./img/favicon-384.png",
"sizes": "384x384",
"type": "image/png"
},
{
"src": "./img/favicon-256.png",
"sizes": "256x256",
"type": "image/png"
},
{
"src": "./img/favicon-192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "./img/favicon-128.png",
"sizes": "128x128",
"type": "image/png"
},
{
"src": "./img/favicon-96.png",
"sizes": "96x96",
"type": "image/png"
},
{
"src": "./img/favicon-32.png",
"sizes": "32x32",
"type": "image/png"
},
{
"src": "./img/favicon-16.png",
"sizes": "16x16",
"type": "image/png"
}
]
}
sw.js (service worker)
// name and version of cache
const CACHE_NAME = 'v1_cache_pwa';
// for cache
var urlsToCache = [
'./',
'./css/styles.css',
'./img/favicon.png',
'./img/1.png',
'./img/2.png',
'./img/3.png',
'./img/4.png',
'./img/5.png',
'./img/6.png',
'./img/favicon-1024.png',
'./img/favicon-512.png',
'./img/favicon-384.png',
'./img/favicon-256.png',
'./img/favicon-192.png',
'./img/favicon-128.png',
'./img/favicon-96.png',
'./img/favicon-64.png',
'./img/favicon-32.png',
'./img/favicon-16.png'
];
// install event
self.addEventListener('install', e => {
e.waitUntil(
caches.open(CACHE_NAME)
.then(cache => {
return cache.addAll(urlsToCache)
.then(() =>{
self.skipWaiting();
});
})
.catch(err => {
console.log('No se ha registrado el cache', err);
})
);
});
// activate event
self.addEventListener('activate', e => {
const cacheWhiteList = [CACHE_NAME];
e.waitUntil(
caches.keys()
.then(cacheNames => {
return Promise.all(
cacheNames.map(cacheName => {
if(cacheWhiteList.indexOf(cacheName) === -1){
// Borrar elementos que no se necesitan
return caches.delete(cacheName);
}
})
);
})
.then(() => {
//Activar cache
self.clients.claim();
})
);
});
// fetch event
self.addEventListener('fetch', function(event) {
event.respondWith(
caches.match(event.request).then(function(response) {
return response || fetch(event.request);
})
);
});
Chrome DevTools audit (on PC)
Testing three apps (ionicPWA example, angularPWA example, my own PWA):
with ionicPWA two warngins appears in the console:
*vendor.js:1: Native: tried calling StatusBar.styleDefault, but Cordova is not available. Make sure to include cordova.js or run in a device/simulator
E
*DevTools failed to parse SourceMap: https://xxx.xxx.xxx/build/sw-toolbox.js.map
(index):28 service worker installed
with AngularPWA no messages/errors/warnings appears...
with my own PWA app, the same behavior.. no messages/errors/warnings appears in the console of Chrome devTools on PC
I have solved the problem. A colleague told me that maybe the problem was due to the port configured on the server.
I had configured the server node.js listening on a specific port (https://mydomain:xxxx), not in the default port (443), and this for some reason caused the PWA application not work in standalone mode on Android.
I set up the server in the default port "443" and the PWA application already works correctly in standalone mode in both Android and iOS.
Thanks to all.

"RESTAPI-INVALIDREQ: (err:FOER0000) Invalid request: reason: invalid patch for uri urlList.json: invalid path: /test/

I have a marklogic database with the following JSON document named urlList.json
{
"test": {
"ip": "10.10.10.10",
"fqdn": "www.test.test"
}
}
I am trying to add to the test object with the marklogic rest API using patch. I am using Node with the request-promise module here is the code
var options = {
method: 'PATCH',
url: 'https://test:8000/v1/documents',
qs: { database: databaseName, uri: 'urlList.json' },
headers:
{
'Content-Type': 'application/json',
Accept: 'application/json'
},
strictSSL: false,
auth: {
user: userName,
pass: password,
sendImmediately: false
},
body: JSON.stringify({
"patch": [
{
"insert": {
"context": "/test/",
"position": "last-child",
"content": { "test": "test"}
}
}
]
})
};
request(options)
.then(results => {
return resolve(results);
})
.catch(err => {
return reject(err);
})
The desired outcome when it runs is
{
"test": {
"ip": "10.10.10.10",
"fqdn": "www.test.test",
"test": "test"
}
}
I get the following error every time I run it
"400 - "{\"errorResponse\":{\"statusCode\":400, \"status\":\"Bad
Request\", \"messageCode\":\"RESTAPI-INVALIDREQ\",
\"message\":\"RESTAPI-INVALIDREQ: (err:FOER0000) Invalid request:
reason: invalid patch for uri urlList.json: invalid path: /test/\"}}""
Here is the body that is sent
"{"patch":[{"insert":{"context":"/test/","position":"last-
child","content":{"test":"test"}}}]}"
A path must select a node. For that reason, a path can't end with a separator. That's what the message attempts to convey.
Does it work with a path of /test?
By the way, MarkLogic provides a Node.js API with support for promises. That might be easier to work with.
Hoping that helps,

Resources