Intercept messages in Swagger UI - swagger

I am trying to intercept response messages in Swagger using this code:
var full = location.protocol + '//' + location.hostname + (location.port ? ':' + location.port : '');
var ui = SwaggerUIBundle({
url: full + "/swagger/v2/swagger.json",
responseInterceptor: function (resp) {
console.log('#response');
return resp;
},
onComplete: function () {
console.log('#onComplete');
}
});
The problem is the response interceptor is called only once (for the https://localhost:5001/swagger/v2/swagger.json file) and it is not called for any API messages.
Is it possible to intercept all swagger API messages?
According to this post it should be possible: https://stackoverflow.com/a/46892528/1882699, but this does not work for me for some reason.

This configuration of Swagger UI works for me is in this post.
The difference is this line:
dom_id: '#swagger-ui',
When this line is used the interceptor intercepts every message. Without this line the interceptor catches only the first message.

Related

SAPUI5 - OData is not defined

I am trying send some data to sap gateway service.
I am using this example the method "save", but when I try do it in my code I get an error "OData is not defined"
Below is the method when I try do it.
handleConfirmationMessageBoxPress: function(oEvent) {
var bCompact = !!this.getView().$().closest(".sapUiSizeCompact").length;
MessageBox.confirm(
"Deseja confirmar a transferência?", {
icon: sap.m.MessageBox.Icon.SUCCESS,
title: "Confirmar",
actions: [sap.m.MessageBox.Action.OK, sap.m.MessageBox.Action.CANCEL],
onClose: function(oAction) {
if (oAction == "OK") {
var oParameters = {};
oParameters.loginfrom = this.getView().byId("multiInput").getValue();
oParameters.loginfrom = this.getView().byId("loginPara").getValue();
oParameters.loginfrom = this.getView().byId("datade").getValue();
oParameters.loginfrom = this.getView().byId("datapara").getValue();
OData.request({
requestUri : "http://<host name>:<port no>/sap/opu/odata/sap/ZMM_EMP_SRV/EmployeeSet",
method : "GET",
headers : {...}
},
function(data, response) {
...
var oHeaders = {
... };
OData.request({
requestUri : "http://<host name>:<port no>/sap/opu/odata/sap/ZMM_EMP_SRV/EmployeeSet",
method : "POST",
headers : oHeaders,
data:oParameters
},
function(data,request) {
MessageToast.show("Transferência realizada!");
location.reload(true);
}, function(err) {
MessageToast.show("A transferência falhou!");
});
}, function(err) {
var request = err.request;
var response = err.response;
alert("Error in Get — Request " + request + " Response " + response);
});
} else {
...
You are attempting to use the OData global object from the datajs library. This library is indeed shipped with OpenUI5, but IMO you should not use it directly (but use the methods of the OData model; there is no real guarantee that UI5 will continue shipping this third-party library in the future).
You are most likely getting the error because the library was not yet loaded by UI5. Libraries are generally lazily loaded by UI5, so you will have to request that UI5 loads it for you (in the tutorial that you have linked, it was loaded behind the scenes by the OData model). To do this, you can either use jQuery.sap.require (jQuery.sap.require("sap.ui.thirdparty.datajs")) or list the dependency inside your sap.ui.define call at the beginning of the controller (e.g. sap.ui.define(['sap/ui/thirdparty/datajs'], function(datajs){...})).
Later edit: you can also use the jQuery.sap.require("sap.ui.model.odata.datajs"); call, but the module was moved from there and it would effectively redirect you to the new location.
this is a very old example, and the used old techniques.
You should add this line to your code:
jQuery.sap.require("sap.ui.model.odata.datajs");
This should solve your oData is undefined problem.
In general you should read newer examples where the read() function of the odata model is used.

iMacros Http POST to API endpoint

I want to do an HTTP POST from inside an iMacro to an API endpoint. Effectively, something like the following:
curl -d "data=foo" http://example.com/API
In iMacros, it might look something like this:
my-imacro.iim
VERSION BUILD=10.4.28.1074
TAB T=1
URL GOTO=javascript:post('http://example.com/API', {data: 'foo'});
function post(path, params, method) {
// Reference: http://stackoverflow.com/a/133997/1640892
method = method || "post";
var form = document.createElement("form");
form.setAttribute("method", method);
form.setAttribute("action", path);
for (var key in params) {
if (params.hasOwnProperty(key)) {
var hiddenField = document.createElement("input");
hiddenField.setAttribute("type", "hidden");
hiddenField.setAttribute("name", key);
hiddenField.setAttribute("value", params[key]);
form.appendChild(hiddenField);
}
}
document.body.appendChild(form);
form.submit();
}
But the above seems like a long and difficult way to do this. If it even works.
Is there a shorter, more direct or efficient solution?
You can use http://wiki.imacros.net/iMacros_for_Firefox with javascript and jquery. Then it's easy with any form, get and post request thing.
Small javascript example with jquery and imacros for firefox:
function loadScriptFromURL(url) {
var request = Components.classes['#mozilla.org/xmlextras/xmlhttprequest;1'].createInstance(Components.interfaces.nsIXMLHttpRequest),
async = false;
request.open('GET', url, async);
request.send();
if (request.status !== 200) {
var message = 'an error occurred while loading script at url: ' + url + ', status: ' + request.status;
iimDisplay(message);
return false;
}
eval(request.response);
return true;
}
loadScriptFromURL('https://ajax.googleapis.com/ajax/libs/jquery/2.2.2/jquery.min.js');
$ = window.$,
JQuery = window.JQuery;
If you are searching for more clean and efficient solution it's need to know that JavaScript will work only in Firefox iMacros plugin. And this script will not work with iMacros plugin version 9.0.3
http://wiki.imacros.net/iMacros_for_Firefox#Version_History
No access to webpage DOM from javascript in .js files (window, content
objects) or macros (URL GOTO=javascript:...)
It's better to change API endpoint method to GET. Next you can create iMacros .iim file that extract from web page some properties and send it by GET method to the API endpoint like http://localhost/endpoint?param1=value1&param2=value2..
' extract header
TAG POS=1 TYPE=span ATTR=id:header EXTRACT=txt
SET !VAR1 header={{!EXTRACT}}
SET !EXTRACT NULL
' extract phone
TAG POS=1 TYPE=span ATTR=class:phone EXTRACT=txt
SET !VAR1 {{!VAR1}}&phone={{!EXTRACT}}
SET !EXTRACT NULL
' ///open new tab
TAB OPEN
TAB T=2
' ///Basic Auth credentials to API Endpoint
ONLOGIN USER=XXX PASSWORD=XXX
URL GOTO=http://localhost:8080/endpoint?{{!VAR1}}

$http error handling in AngularJS

$http in my AngularJS project not able to recognize 40X(401,403,405...) errors on iOS.
I am using 1.2.10 AngularJS version and Cordova version 3.4.0.
Below is the code I am using:
TE_SERVICES.factory('hello',function ($http,$rootScope) {
return {
loginUser: function(userCredentials,successCallback,errorCallback){
$http({
method: "GET",
url: "data/example.json",
headers: {"Authorization":'Basic '+userCredentials},
}).then(function(response){
successCallback(response.data);
console.log("Success------"+JSON.stringify(response))
},function(data, status, headers, config){
errorCallback(data);
console.log("Error------"+JSON.stringify(data)+" "+status)
})
}
}
});
hello.loginUser($rootScope.encodedUserCredencials,function(persons) {
// success handler
}, function(data) {
// error handler
console.log(data.status+"===="+status)
});
data.status is returning 0 and status returns undefined.
Please help me to resolve this issue.
Tried to include the domain in whitelist on IOS.But no solution :( It still gives the same response.
But the same code works absolutely fine in Android.
Please help me to resolve this issue.
Thanks in advance :)
So you r using the $http from angular. Do you use the error callback or the second function in the then callback ?
Example
$http.get("someUrl")
.success(function(response){}) // if http code == 200
.error(function(response){}) // else
Or with then, that can take 2 functions. The first is the onSuccess, the second the onError function.
$http.get("someUrl")
.then(function(response){
// if http code == 200
},
function(response){
// else
});
The response parameter does also contain the error codes.
Consider using a $httpInterceptor to handle all errorcodes at the same place, instead handling them in every http callback.
UPDATE:
It seems, that the angular doc is incomplete/wrong for the success callback.
It doesnt pass 4 parameter there. It does pass a response object that contains all the information about request+response and the passed data.
Update to the edit:
Dont write callbacks by yourself. Use angular promises:
TE_SERVICES.factory('hello',function ($http,$rootScope) {
return {
loginUser: function(userCredentials){
return $http({
method: "GET",
url: "data/example.json",
headers: {"Authorization":'Basic '+userCredentials},
}).then(function(response){
return response.data;
},function(response){
return response;
});
}
}
});
hello.loginUser($rootScope.encodedUserCredencials)
.then(function(persons) { // success handler
}, function(data) { // error handler
console.log(data);
});
Try this and tell me if the console.log logs something.
I had exactly the same problem. Cordova app, angular js, IPhone and 401 requests are not received in angular js http interceptor. They work fine on android devices.
My finding was that IPhone browser is handling those at a higher lever and trying to use WWW-Authenticate information to do authentication. This is why the response does not get to angular.
The only solution I found, was to change my service to return 400 instead of 401 in case of an api request. In this case I return 400 with an error message that I handle on client side.
I hope this helps.
My issue with the 403 status code was that my backend returned a response with status 403 but the body of a response did not contain a JSON string. It contained just a string - Authentication Failed.
The rejection variable was an object Error.
I encoded the body and the rejection variable contains a valid response error object.
To handle HTTP errors I use interceptors.
$httpProvider.interceptors.push(function($q, $location, redirect, HTTP_CODES) {
return {
'responseError': function(rejection) {
if (rejection.status === HTTP_CODES.FORBIDDEN) {
redirect('/login', $location.url());
}
return $q.reject(rejection);
}
};
});

two way communication between extension and content javascript files

i am trying to accomplish a two way communication request response in my firefox sidebar extension, i have a file named event.js this resides on the content side, i have another file called sidebar.js file which is residing in the xul. I am able to communicate from event.js to sidebar.js file using the dispatchEvent method. my event in turn raises a XMLHttpRequest in sidebar.js file which hits the server and sends back the response. Now, here i am unable to pass the response to the event.js file. I want the response to be accessed in the event.js file. Till now i have achieved only one way communication. Please help me in getting the two way communication.
Code is as follows:
// event.js file
// This event occurs on blur of the text box where i need to save the text into the server
function saveEvent() {
var element = document.getElementById("fetchData");
element.setAttribute("urlPath", "http://localhost:8080/event?Id=12");
element.setAttribute("jsonObj", convertToList);
element.setAttribute("methodType", "POST");
document.documentElement.appendChild(element);
var evt = document.createEvent("Events");
evt.initEvent("saveEvent", true, true);
element.dispatchEvent(evt);
//Fetching the response over here by adding the listener
document.addEventListener("dispatchedResponse", function (e) { MyExtension.responseListener(e); }, false, true);
}
var MyExtension = {
responseListener: function (evt) {
receivedResponse(evt.target.getAttribute("responseObject"));
}
}
function receivedResponse(event) {
alert('response: ' + event);
}
// sidebar.js file
window.addEventListener("load", function (event) {
var saveAjaxRequest = function (urlPath, jsonObj, methodType, evtTarget) {
var url = urlPath;
var request = Components.classes["#mozilla.org/xmlextras/xmlhttprequest;1"].createInstance(Components.interfaces.nsIXMLHttpRequest);
request.onload = function (aEvent) {
window.alert("Response Text: " + aEvent.target.responseText);
saveResponse = aEvent.target.responseText;
//here i am again trying to dispatch the response i got from the server back to the origin, but unable to pass it...
evtTarget.setAttribute("responseObject", saveResponse);
document.documentElement.appendChild(evtTarget);
var evt = document.createEvent("dispatchedRes"); // Error line "Operation is not supported" code: "9"
evt.initEvent("dispatchedResponse", true, false);
evtTarget.dispatchEvent(evt);
};
request.onerror = function (aEvent) {
window.alert("Error Status: " + aEvent.target.status);
};
//window.alert(methodType + " " + url);
request.open(methodType, url, true);
request.send(jsonObj);
};
this.onLoad = function () {
document.addEventListener("saveEvent", function (e) { MyExtension.saveListener(e); }, false, true);
}
var MyExtension =
{
saveListener: function (evt) {
saveAjaxRequest(evt.target.getAttribute("urlPath"), evt.target.getAttribute("jsonObj"), evt.target.getAttribute("methodType"), evt.originalTarget);
}
};
});
Why are you moving your fetchData element into the sidebar document? You should leave it where it is, otherwise your content code won't be able to receive the event. Also, use the content document to create the event. Finally, document.createEvent() parameter for custom events should be "Events". So the code after your //here i am again trying comment should look like:
evtTarget.setAttribute("responseObject", saveResponse);
var evt = evtTarget.ownerDocument.createEvent("Events");
evt.initEvent("dispatchedResponse", true, false);
evtTarget.dispatchEvent(evt);
Please note however that your code as you show it here is a huge security vulnerability - it allows any website to make any HTTP requests and get the result back, so it essentially disables same-origin policy. At the very least you need to check that the website talking to you is allowed to do it (e.g. it belongs to your server). But even then it stays a security risk because server response could be altered (e.g. by an attacker on a public WLAN) or your server could be hacked - and you would be giving an attacker access to sensitive data (for example he could trigger a request to mail.google.com and if the victim happens to be logged in he will be able to read all email data). So please make this less generic, only allow requests to some websites.

XMLHttpRequest different in IE8 vs. FireFox/Chrome

I'm having a problem similar to jQuery $.ajax Not Working in IE8 but it works on FireFox & Chrome, but with a different use case.
I'm using the jQuery Form plug-in to handle a file upload to an ASP.NET MVC controller, which sends the file off for parsing and processing. If an Exception is thrown, it should alert the user to the issue.
//client side code
//make an ajax call, sending the contents of the file
$("#ajaxUploadForm").ajaxSubmit({
dataType: 'json',
url: '/plan/Something/ExcelImport',
iframe: true,
beforeSend: function () {
$(".ui-dialog-buttonpane").find("#my_progress").fadeIn();
},
success: function (data, textStatus) {
output = "<center><span class='flash'>" + data.message + "</span></center>";
$("#flash_message").html(output).fadeIn('slow');
setTimeout(function () { $("#flash_message").fadeOut() }, 5000);
cleanup();
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
alert("XMLHttpRequest is " + XMLHttpRequest);
var contents = "";
for (prop in XMLHttpRequest) {
contents += "\na property is " + prop + " it's value is " + XMLHttpRequest[prop];
}
alert("the contents are " + contents);
alert("textStatus is " + textStatus);
alert("errorThrown is " + errorThrown);
//comes back in an HTML envelope. This should be parsed with regex, but I can't get it to work. Dirty hack
response = XMLHttpRequest.responseText.substring(XMLHttpRequest.responseText.indexOf("<body>"));
response = response.replace("<body>", "");
response = response.replace("</body>", "");
alert("There was a problem with the upload.\r\n" + response);
},
complete: function (XMLHttpRequest, textStatus) {
$(".ui-dialog-buttonpane").find("#my_progress").remove();
something_import.dialog('close');
something_import.dialog('destroy');
}
});
//server side code
public FileUploadJsonResult ExcelImport()
{
FileUploadJsonResult result = new FileUploadJsonResult();
HttpPostedFileBase hpf = Request.Files[0] as HttpPostedFileBase;
if (hpf.ContentLength == 0)
return new FileUploadJsonResult { Data = new { message = "File contained no data" } };
String fileName = Path.GetFileName(hpf.FileName);
String timeStampedFile = fileName.Insert(fileName.IndexOf('.'),"_"+DateTime.Now.ToFileTimeUtc());
string savedFileName = Path.Combine(AppDomain.CurrentDomain.BaseDirectory + "tempo", timeStampedFile);
hpf.SaveAs(savedFileName);
try
{
result = ProcessFile(savedFileName, Request["Id"]) as FileUploadJsonResult;
}
catch (ArgumentException e)
{
this.Response.StatusCode = 500;
this.Response.StatusDescription = System.Net.HttpStatusCode.BadRequest.ToString();
Response.Write(e.Message);
result = Json(new { message = e.Message, stackTrace = e.StackTrace }) as FileUploadJsonResult;
}
return result;
}
This works perfectly in Chrome and Firefox. In IE, the XMLHttpRequest object coming back is different:
FF:
IE:
I've been Googling around for differences between the browser implementations of XMLHttpRequest, but haven't found anything that deals specifically with this case. Stymied.
The reason this is happening is because of the iframe fallback strategy that ajaxSubmit employs. I think since the response gets posted into the iframe IE tries to figure out how to dipslay it and decides that it wants to ask you to download the response instead of just putting it in the iframe.
I came across this same situation a while ago and found an article (that I can't find now) that offered a workaround.
If you surround your json response in a textarea nobody is going to complain(IE,FF,Chrome,probably Safari) and you'll get your response parsed correctly.
E.g. if you are returning
{Id: 1, Name: 'Me'}
just return:
<textarea>{Id: 1, Name: 'Me'}</textarea>
You see now IE thinks it's html so it inserts it into the hidden iframe. Your ajaxSubmit function still gets called and parses the json correctly and then everybody's happy. :)
If you're using ASP.NET MVC you could shamelessly copy this extension method :)
public static class ControllerExtensions
{
public static ActionResult JsonSafe(this IController controller, object obj)
{
JavaScriptSerializer serializer = new JavaScriptSerializer();
return new WriteResult(string.Format("<textarea>{0}</textarea>", serializer.Serialize(obj)));
}
}
The wikipedia article on XMLHttpRequest seems to give a good overview of the history behind the XMLHttpRequest. It seems Microsoft and Mozilla developed/adopted their own versions of the object and hence why you are probably seeing different properties.
Here is a link to Microsoft's implementation of the XMLHttpRequest interface members, which seem to match the properties in your alert.
Here is the a link to Mozilla's implementation of XMLHttpRequest.
So while we wait for the W3C to standardize the XMLHttpRequest you will continue to have different implementations across the browsers like you are seeing in this case.
For some added fun here is Apple's and Opera's specifications on XMLHttpRequest.

Resources