Add token in headers to display swagger UI - swagger

I am stuck on something stupid : I want to display the documentation for each route with swagger only if I give a correct api-key. How can I achieve that? Where can I configure the headers when I try to load the UI?
I tried that :
$('#input_apiKey').change(function() {
var key = $('#input_apiKey')[0].value;
if(key && key.trim() != "") {
swaggerUi.api.clientAuthorizations.add("key", new SwaggerClient.ApiKeyAuthorization("api_key", key, "header"));
}
})
But it doesn't appear in the request headers.

Related

ActionDispatch::ParamsParser::ParseError for String Request Payload

I'm receiving a standard request from an API. It looks something like this :
It's content type and length is :
But when this hits my Rails server, Rails responds with
The reason I'm bringing this up, is because the same request seems to work on SCORM Cloud's server. If I upload the exact same content to them, and watch it in the debugger, I see it send out an application/json statement with the same Request payload, but with no unexpected token error.
Does a Rails application/json request have to be written a certain way that differs from other servers? Is there a proper way to rewrite this line in Rack Middleware to prevent this error?
Update
The javascript :
function _TCDriver_XHR_request (lrs, url, method, data, callback, ignore404, extraHeaders) {
_TCDriver_Log("_TCDriver_XHR_request: " + url);
var xhr,
finished = false,
xDomainRequest = false,
ieXDomain = false,
ieModeRequest,
title,
ticks = ['/', '-', '\\', '|'],
location = window.location,
urlParts,
urlPort,
result,
extended,
until,
fullUrl = lrs.endpoint + url
;
urlParts = fullUrl.toLowerCase().match(/^(.+):\/\/([^:\/]*):?(\d+)?(\/.*)?$/);
// add extended LMS-specified values to the URL
if (lrs.extended !== undefined) {
extended = [];
for (var prop in lrs.extended) {
if(lrs.extended[prop] != null && lrs.extended[prop].length > 0){
extended.push(prop + "=" + encodeURIComponent(lrs.extended[prop]));
}
}
if (extended.length > 0) {
fullUrl += (fullUrl.indexOf("?") > -1 ? "&" : "?") + extended.join("&");
}
}
//Consolidate headers
var headers = {};
headers["Content-Type"] = "application/json";
headers["Authorization"] = lrs.auth;
if (extraHeaders !== null) {
for (var headerName in extraHeaders) {
headers[headerName] = extraHeaders[headerName];
}
}
//See if this really is a cross domain
xDomainRequest = (location.protocol.toLowerCase() !== urlParts[1] || location.hostname.toLowerCase() !== urlParts[2]);
if (! xDomainRequest) {
urlPort = (urlParts[3] === null ? ( urlParts[1] === 'http' ? '80' : '443') : urlParts[3]);
xDomainRequest = (urlPort === location.port);
}
//If it's not cross domain or we're not using IE, use the usual XmlHttpRequest
if (! xDomainRequest || typeof XDomainRequest === 'undefined') {
_TCDriver_Log("_TCDriver_XHR_request using XMLHttpRequest");
xhr = new XMLHttpRequest();
xhr.open(method, fullUrl, callback != null);
for (var headerName in headers) {
xhr.setRequestHeader(headerName, headers[headerName]);
}
}
//Otherwise, use IE's XDomainRequest object
else {
_TCDriver_Log("_TCDriver_XHR_request using XDomainRequest");
ieXDomain = true;
ieModeRequest = _TCDriver_GetIEModeRequest(method, fullUrl, headers, data);
xhr = new XDomainRequest ();
xhr.open(ieModeRequest.method, ieModeRequest.url);
}
Rails is being "helpful" here and assuming that the client is correctly using "Content-Type" and passing a value that actually matches that content type. In other words, the payload in the request has to be parseable JSON, and the value being passed is not valid JSON.
Which is an entirely reasonable thing for it to do when you are implementing an in house API that isn't intended for maximum interoperability. What Rails doesn't know is that an LRS' document storage is supposed to be "dumb" and basically allow the client to shove whatever it wants in and get whatever it wants out, which is why SCORM Cloud accepts the request, basically it just stores the content type and the contents, and then regurgitates them as is on request.
The code you pasted is from a very old library that has poor implementation of Content-Type headers. If this code is found anywhere other than in a relatively old version of a piece of content from one of the major e-learning authoring tools then it should be updated to use a recent version of TinCanJS and improve the content type handling.
As far as making this work on Rails, sorry I don't have that much experience with it. Presumably there is a switch or something to turn off automatic request body parsing, at least that's what most other frameworks I've used have.
Does a Rails application/json request have to be written a certain way that differs from other servers?
Not that I know of no.
Is there a proper way to rewrite this line in Rack Middleware to prevent this error?
There might a way yes, maybe even without rack middlewares, although it's quite hard to help you without an actual request to work with.

Unable to figure out how to use post method, for a suitescript written in Netsuite

I am trying to do use the post method for a simple suitescript program, i am very new to this.
In Netsuite i have written a suitescript as follows.
function restPost()
{
var i = nlapiLoadRecord('department', 115);
var memo = nlapisetfieldvalue('custrecord225', ' ');// this is a customfield, which i want to populate the memo field, using rest client in firefox
var recordId = nlapiSubmitRecord(i);
}
i have created a script record and uploaded this suitescript and even copied the external URL to paste it in restclient.
In Restclient(firefox plugin), pasted the external URL, i have given the method as post, header authorization given, content-type: application/json, and in body i put in {"memo":"mynamehere"};
In this the error i get is
message": "missing ) after argument list
I even tried it by writting other suitescript programs the errors i get is as follows:
Unexpected token in object literal (null$lib#3) Empty JSON string
Invalid data format. You should return TEXT.
I am kinda new to the programming world, so any help would be really good.
I think you are trying to create a RESTlet for POST method. Following is the sample code for POST method -
function createRecord(datain)
{
var err = new Object();
// Validate if mandatory record type is set in the request
if (!datain.recordtype)
{
err.status = "failed";
err.message= "missing recordtype";
return err;
}
var record = nlapiCreateRecord(datain.recordtype);
for (var fieldname in datain)
{
if (datain.hasOwnProperty(fieldname))
{
if (fieldname != 'recordtype' && fieldname != 'id')
{
var value = datain[fieldname];
if (value && typeof value != 'object') // ignore other type of parameters
{
record.setFieldValue(fieldname, value);
}
}
}
}
var recordId = nlapiSubmitRecord(record);
nlapiLogExecution('DEBUG','id='+recordId);
var nlobj = nlapiLoadRecord(datain.recordtype,recordId);
return nlobj;
}
So after deploying this RESTlet you can call this POST method by passing following sample JSON payload -
{"recordtype":"customer","entityid":"John Doe","companyname":"ABCTools Inc","subsidiary":"1","email":"jdoe#email.com"}
For Authorization you have to pass request headers as follows -
var headers = {
"Authorization": "NLAuth nlauth_account=" + cred.account + ", nlauth_email=" + cred.email +
", nlauth_signature= " + cred.password + ", nlauth_role=" + cred.role,
"Content-Type": "application/json"};
I can understand your requirement and the answer posted by Parsun & NetSuite-Expert is good. You can follow that code. That is a generic code that can accept any master record without child records. For Example Customer Without Contact or Addressbook.
I would like to suggest a small change in the code and i have given it in my solution.
Changes Below
var isExistRec = isExistingRecord(objDataIn);
var record = (isExistRec) ? nlapiLoadRecord(objDataIn.recordtype, objDataIn.internalid, {
recordmode: 'dynamic'
}) : nlapiCreateRecord(objDataIn.recordtype);
//Check for Record is Existing in Netsuite or Not using a custom function
function isExistingRecord(objDataIn) {
if (objDataIn.internalid != null && objDataIn.internalid != '' && objDataIn.internalid.trim().length > 0)
return true;
else
return false;
}
So whenever you pass JSON data to the REStlet, keep in mind you have
to pass the internalid, recordtype as mandatory values.
Thanks
Frederick
I believe you will want to return something from your function. An empty object should do fine, or something like {success : true}.
Welcome to Netsuite Suitescripting #Vin :)
I strongly recommend to go through SuiteScript API Overview & SuiteScript API - Alphabetized Index in NS help Center, which is the only and most obvious place to learn the basics of Suitescripting.
nlapiLoadRecord(type, id, initializeValues)
Loads an existing record from the system and returns an nlobjRecord object containing all the field data for that record. You can then extract the desired information from the loaded record using the methods available on the returned record object. This API is a core API. It is available in both client and server contexts.
function restPost(dataIn) {
var record = nlapiLoadRecord('department', 115); // returns nlobjRecord
record.setFieldValue('custrecord225', dataIn.memo); // set the value in custom field
var recordId = nlapiSubmitRecord(record);
return recordId;
}

Using Google Script to send an email with a Word doc attachment

I have a google script that sends an email with a Word doc as an attachment. It used to work until google deprecated OAuth 1.0
This is the line that's failing:
var doc = UrlFetchApp.fetch(url+'download/documents/Export?exportFormat=doc&format=doc&id='+ copyId, googleOAuth_('docs',url)).getBlob();
If I remove the second parameter, i.e. function call to OAuth, it should work? Why do I need to authenticate? It should be able to fetch the document using an ID from google drive. It appears to work (because I don't see any errors), however, when I get an email there is a corrupt word doc attachment.
So, I tried implementing OAuth 2.0. But I'm not getting anywhere. Here's my code:
function getDriveService() {
return OAuth2.createService('drive')
.setAuthorizationBaseUrl('https://accounts.google.com/o/oauth2/auth')
.setTokenUrl('https://accounts.google.com/o/oauth2/token')
.setClientId(CLIENT_ID)
.setClientSecret(CLIENT_SECRET)
.setCallbackFunction('authCallback')
.setPropertyStore(PropertiesService.getUserProperties())
.setScope('https://www.googleapis.com/auth/drive')
.setParam('login_hint', Session.getActiveUser().getEmail())
.setParam('access_type', 'offline');
//.setParam('approval_prompt', 'force');
}
function authCallback(request) {
var driveService = getDriveService();
var isAuthorized = driveService.handleCallback(request);
if (isAuthorized) {
return HtmlService.createHtmlOutput('Success! You can close this tab.');
} else {
return HtmlService.createHtmlOutput('Denied. You can close this tab');
}
}
var oauth2Service = getDriveService();
var token = oauth2Service.getAccessToken();
var parameters = { method : 'get',
headers : {'Authorization': 'Bearer '+ token}};
var options =
{
"method" : "get"
};
var resp = UrlFetchApp.fetch('https://docs.google.com/feeds/download/documents/Export?exportFormat=doc&format=doc&id='+ copyId, parameters);
doc = resp.getBlob();
I'm getting a generic error [Access not granted or expired]. All I want is to be able to send an email with an attachment that is a document (format doc or docx) stored from my Google drive. Seems impossible! I'm able to attach this doc as a pdf but NOT a Microsoft document.
Any help will be greatly appreciated!
https://github.com/googlesamples/apps-script-oauth2 - look at setup
...
Have you added OAuth 2.0 in the libraries?
Resources -> Libraries -> then add 'MswhXl8fVhTFUH_Q3UOJbXvxhMjh3Sh48'

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

Working with XML in a Firefox Add-on(ex Jetpack)

I'm currently developing a Firefox add-on(using https://addons.mozilla.org/en-US/developers/docs/sdk/1.0/ ) that consumes an API where the return data is in xml.
My problem is that I need to parse the returned data, and would like to do that using a xml object.
Since the request module only supports JSON and Text ( https://addons.mozilla.org/en-US/developers/docs/sdk/1.0/packages/addon-kit/docs/request.html#Response ) I need to convert the response.text to XML.
The code looks like this:
var Request = require('request').Request
.......
var req = Request({
url: https://to-the-api.com,
content: {
op: 'get-the-data-op',
password: "super-sec",
user: "username"
},
onComplete: function (response) {
dataAsText = response.text;
console.log("output: " + dataAsText);
}
});
req.post();
I have tried to user (new DOMParser).parseFromString(response.text, 'text/xml') but unfortunately it just fails with a error like ReferenceError: DOMParser is not defined
The question is if anyone of you guys have been able to create a Xml object inside a Firefox add-on, and if so, how?
Looks like the capability to parse response as xml was present, but has been removed. check out this bugzilla reference
Can't you use a normal XMLHttpRequest if you want to process the response as XML?
If DOMParser is unavailable you can try E4X:
var xml = new XML(response.text);
alert(xml.children().length());
You want to use the XMLHttpRequest object to handle your xhr request. Then when you get a response back access the responseXML object of the request variable. In the responseXML you'll have the documentElement and can use the querySelectorAll or querySelector to find elements you want. In each element you want just grab the textContent you need.
Here's an example to get you going (this looks for the 'xmls' element in the response):
var request = new require("xhr").XMLHttpRequest();
request.open('GET', 'https://to-the-api.com', true);
request.onreadystatechange = function (aEvt) {
if (request.readyState == 4) {
if(request.status == 200) {
var xmls = request.responseXML.documentElement.querySelectorAll("xmls");
for (var i = 0; i < xmls.length; i++) {
console.log("xml", i, xmls[i], xmls[i].textContent);
}
}
else {
console.log('Error', request.responseText);
}
}
};
request.send(null);

Resources