I'm trying to setup a simple login API using node.js/restify. The code below shows a simple route, with nothing but a console.log() statement within it, as I'm just trying to prove I can gain a connection.
var restify = require('restify');
var user = require('./user');
var reference = require('./reference');
var fs = require('fs');
var bodyParser = require('body-parser');
var _= require('lodash');
const server = restify.createServer();
server.use(bodyParser.json());
server.use(bodyParser.urlencoded({extended:false}));
server.use(restify.plugins.fullResponse())
server.use(restify.plugins.bodyParser());
server.use(restify.plugins.queryParser()) server.use(restify.plugins.authorizationParser())
var port = 8080;
server.post('/user/login', (req, res) => {
console.log("---LOGIN ATTEMPT---");
res.status(200);
res.end();
});
Using Postman for testing, I expect to get a statement back in the console, stating "LOGIN ATTEMPT".
Postman freezes with the 'Loading' text and stays like that until it crashes saying 'There was an error connecting to localhost:8080/user/login'. This only occurs when sending JSON data and not when sending form-data, which is where my confusion is occurring. It is acting as if an infinite loop is occurring with JSON data but can not trace where it is happening.
because you are not sending any data back to requesting browser(in this case postman) try returning some response as body
for example use res.send('success')
Related
I am new to Forge and using node.js - I am having some difficulty getting a simple 3-legged Oauth process to work.
This is how far I have got below. It gives me the error "Cannot GET /api/forge/oauth/callback"
I have checked that my callback url matches what is in the Forge App.
Ultimately what I am trying to achieve is, getting the shared link for a newly created file in Fusion teams, or at least opening the browser to the file overview page.
Would anybody be able to help with this?
var express = require('express');
var ForgeSDK = require('forge-apis');
const { stringify } = require('node:querystring');
var opn = require('opn');
// Set up Express web server
var app = express();
// Set the Forge Variables
var FORGE_CLIENT_ID = 'client-id', FORGE_CLIENT_SECRET = 'client-secret', REDIRECT_URL = 'http://localhost:3000/api/forge/oauth/callback';
// This is for web server to start listening to port 3000
app.set('port', 3000);
var server = app.listen(app.get('port'), function () {
console.log('Server listening on port ' + server.address().port);
});
// Initialize the 3-legged OAuth2 client, set specific scopes and optionally set the `autoRefresh` parameter to true
// if you want the token to auto refresh
var autoRefresh = true;
var oAuth2ThreeLegged = new ForgeSDK.AuthClientThreeLegged(FORGE_CLIENT_ID, FORGE_CLIENT_SECRET, REDIRECT_URL, [
'data:read',
'data:write'
], autoRefresh);
// Generate a URL page that asks for permissions for the specified scopes.
var AuthURL = oAuth2ThreeLegged.generateAuthUrl();
console.log(AuthURL)
opn('https://developer.api.autodesk.com/authentication/v1/authorize?response_type=code&client_id=<<client-id>>&redirect_uri=http://localhost:3000/api/forge/oauth/callback&scope=data:read+data:write&state=undefined', {app: 'chrome'})
where is the callback API in your code?
BTW 3-Legged oauth is implemented here in nodejs, you can use it as reference:
https://learnforge.autodesk.io/#/oauth/3legged/nodejs
I've attached the following code to a Submit Button in Google Forms:
function generateQueryString(data) {
const params = [];
for (var d in data)
params.push(encodeURIComponent(d) + '=' + encodeURIComponent(data[d]));
return params.join('&');
}
function ctrlqFormSubmit(event) {
// The event is a FormResponse object:
// https://developers.google.com/apps-script/reference/forms/form-response
var formResponse = event.response;
// Gets all ItemResponses contained in the form response
// https://developers.google.com/apps-script/reference/forms/form-response#getItemResponses()
var itemResponses = formResponse.getItemResponses();
// Gets the actual response strings from the array of ItemResponses
var responses = itemResponses.map(function getResponse(e) { return e.getResponse(); });
// Post the payload as JSON to our Cloud Function
var response = UrlFetchApp.fetch('http://<**MY DOMAIN HERE**:3001>/formdir?' + generateQueryString(responses));
Logger.log(response.getContentText());
}
Unfortunately, the Trigger fails with the message:
Exception: DNS error: http://**MY DOMAIN HERE**:3001/formdir?0=Name&1=&2=Biz&3=Research&4=&5=&6=&7=&8=Other&9=&10=&11=&12=&13=&14=
at ctrlqFormSubmit(SubmitFcn:18:30)
But if I copy this exact string in my browser, I get the expected result. Also, when I use NSLOOKUP with this domain on the command line, the IP's return as expected. The domain even resolves when I go to https://dns.google/...
The text of error itself seems to indicate the function is working, and it's a GET request, which is why I'm using Query Parameters, but the DNS name is not resolving in the script. I even used one of the IPs and got the same error.
SOLVED: Even though the domain used above was public-facing, the AWS Load Balancer it uses was configured with a "REDIRECT" to an internal domain. It was this second domain that caused the DNS Error, even though the message references the external domain. I changed the load balancer action from "redirect" to "forward", and now all is well.
I'm trying to use the CloudKit Web Services API to fetch Article records from my production CloudKit container's public database within Google Apps Script.
My request is based on the documentation on this page.
Here's my code:
// variables for the CloudKit request URL
var path = "https://api.apple-cloudkit.com";
var version = "1";
var container = "iCloud.com.companyname.My-Container-Name";
var environment = "production";
var database = "public";
var token = "8888888888888_my_actual_token_88888888888888888"
function showArticles() {
// assemble the URL
var url = path + "/database/" + version + "/" + container + "/" + environment + "/" + database + "/records/query?ckAPIToken=" + token;
// specify the record type to query
var query = {
recordType: "Article"
};
// specify the payload for the POST request
var payload = {
query : query
};
// set up the fetch options for the fetch request
var options = {
method : "POST",
payload : payload
};
// make the request
var response = UrlFetchApp.fetch(url, options);
Logger.log(response);
}
UrlFetchApp.fetch(url, options) fails with this error:
Request failed for https://api.apple-cloudkit.com/database/1/iCloud.<?>-Container-Name/development/public/records/query?ckAPIToken=8888888888888_my_actual_token_88888888888888888 returned code 401. Truncated server response: {"uuid":"7d8a8547-ad08-4090-b4b3-917868a42f6f","serverErrorCode":"AUTHENTICATION_FAILED","reason":"no auth method found"} (use muteHttpExceptions option to examine full response) (line 30, file "Code")
I've been troubleshooting for a few hours and I can't figure out what I'm doing wrong. I've tried it with a separate token on my development environment, too, and the same thing happens.
This page mentions the ckWebAuthToken parameter and says "if omitted and required, the request fails," but I can't find anything that says what requests require a ckWebAuthToken. I'm assuming I don't need ckWebAuthToken since the records I'm trying to access are in my container's public database, and I'm getting an AUTHENTICATION_FAILED error rather an AUTHENTICATION_REQUIRED error.
One part that confuses me is this URL that comes up in the error message:
https://api.apple-cloudkit.com/database/1/iCloud.<?>-Container-Name/development/public/records/query?ckAPIToken=8888888888888_my_actual_token_88888888888888888
I would expect it to be:
https://api.apple-cloudkit.com/database/1/iCloud.com.companyname.My-Container-Name/development/public/records/query?ckAPIToken=8888888888888_my_actual_token_88888888888888888
But I can't tell if that's actually the URL that's being requested, and when I log the url variable everything looks fine.
Thanks in advance for any troubleshooting tips or solutions!
UPDATE
I tried using Postman, and the request worked with same endpoint and POST data. It looks like the container component of the URL is getting corrupted by the Google Apps Script UrlFetchApp.fetch() method. The <?> seems to only show up when com. is in the URL.
I'm not sure why this is the answer, but I was able to get it working by using JSON.stringify() on the payload in options:
var options = {
method : "POST",
payload : JSON.stringify(payload)
};
I have the following code which accepts data from the url and print the json formatted data.I want to publish the same data to mqtt using node.js.Is there any sample code for the same?
`var request = require('request')
var JSONStream = require('JSONStream')
`var es = require('event-stream')`
`request({url: 'http://isaacs.couchone.com/registry/_all_docs'})
`.pipe(JSONStream.parse('rows.*'))
.pipe(es.mapSync(function (data) {
console.log(data);
console.error(data)
return data
}))
You could use the mqtt node library MQTT.js
Your current code becomes something like that:
var request = require('request');
var JSONStream = require('JSONStream');
var es = require('event-stream');
var mqtt = require('mqtt');
request({url: 'http://isaacs.couchone.com/registry/_all_docs'})
.pipe(JSONStream.parse('rows.*'))
.pipe(es.mapSync(function (data) {
console.log(data);
console.error(data);
//MQTT publish starts here
var client = mqtt.createClient(1883, 'localhost');
client.publish('demoTopic', JSON.stringify(data));
client.end();
return data;
}))
The above code assumes the broker is running on the local machine on port 1883.
Just use a node.js library for mqtt such as MQTT.js https://github.com/adamvr/MQTT.js
Also you can run your own multi-protocol broker in node.js by installing mosca https://github.com/mcollina/mosca
Looking for some help connecting to this service and returning the xml.
Here are the instructions (from here):
The state of the inputs and relays can be monitored by sending a
request to port 80 (or port specified in setup) for the XML page
state.xml. The relays can be controlled by sending GET requests to the
same page on port 80 (or port specified in setup). This can be
demonstrated by entering commands into the URL line of a web browser.
Request the current state: http://"ip address"/state.xml
...
If the control password is enabled in the WebRelay-DualTM unit and
the state.xml page is requested through a browser, the browser will
prompt the user for the password. If the XML request is sent from
another application and not a browser, the html request will need to
contain the password encoded using the base 64 encoding scheme. The
html request header without the password looks like this:
GET /state.xml?relay1State=1&noReply=1 HTTP/1.1 (Ends with two \r\n)
The html request header with the password looks like this:
GET /state.xml?relay1State=1&noReply=1 HTTP/1.1(\r\n here)
Authorization: Basic bm9uZTp3ZWJyZWxheQ== (Ends with two \r\n)
where bm9uZTp3ZWJyZWxheQ== is the base 64 encoded version of the
user name and password none:webrelay
Code:
function webRelay(){
//working url http://75.65.130.27/state.xml
var url = 'http://75.65.130.27/';
var params = encodeURIComponent('state.xml');
Logger.log(params);
var headers = {
"Authorization" : "Basic" + Utilities.base64Encode('none:webrelay')
};
var options =
{
"method" : "get",
"headers" : headers
};
var state = UrlFetchApp.fetch(url+params, options);
Logger.log('1: '+state);
Logger.log(parse(state));
}
function parse(txt) {
var doc = Xml.parse(txt, true);
}
Any help is much appreciated.
There are a couple of coding errors that you can easily take care of:
In the Authorization header you need a space after "Basic".
Authorization : "Basic " + Utilities.base64Encode(username+':'+password)
urlFetchApp.fetch() returns an HTTP Response object, so you need to extract the contents for parsing.
var result = UrlFetchApp.fetch(url, options);
var state = result.getContentText();
You aren't returning anything from your parse() function.
You should check result.getResponseCode() after .fetch(), and handle errors before proceeding with parsing.
That said, I keep getting Bad request: http://75.65.130.27/state.xml errors, so something is still not right. This is an HTTP 400 response, and google's servers don't return anything to the script debugger to dig into it. You should check the username & password, although I'd expect a 401-Unauthorized response if they were wrong. I tried including a payload of relay1State=2, and got the same Bad request result. If you can capture the HTTP Request hitting your server, there may be a clue to what is malformed. This could also be the result of a firewall.
Once that's sorted, this tutorial should help with the XML Parsing.
Here's my edit of your code:
function webRelay(){
var url = 'http://75.65.130.27/state.xml';
var username = "none";
var password = "webrelay";
var headers =
{
Authorization : "Basic " + Utilities.base64Encode(username+':'+password)
}
var options =
{
"method" : "get",
"headers": headers
};
// Getting "bad request" here - check the username & password
var result = UrlFetchApp.fetch(url, options);
var state=result.getContentText();
// You should check state.getResponseCode()
Logger.log('1: '+state);
Logger.log(parse(state));
}
function parse(txt) {
var doc = Xml.parse(txt, true);
return doc; // Return results
}