Dynamic Json result from RestAPI not being returned to Angular controller - json

I have Json data being pulled from a REST API. On success I have created a simple alert that will display the Json results inside of an $http.get. I found a sample URL that points to Json data online for testing and I get the alert with the results just fine. But when I try to do this with my URL pointing back to the api, I get no results (not even an alert). However, when I take that same URL and put it into the browser, all of my Json data is there. Any ideas or thoughts on what might be causing this issue? Thanks.
JavaScript (with test Json data)
var myApp = angular.module('paladinMonitor', ["highcharts-ng"]);
myApp.controller('SizeCtrl', function ($scope, $http, $timeout) {
$http.get('http://ip.jsontest.com/?callback=showMyIP').success(function (data, status) {
alert(data)
});

I had something similar happen to me. Restful web services must use the Access-Control-Allow-Origin header to specify what origins are allowed to access the service. Without it, you can hit the web service successfully by putting the address directly in your browser but it won't work from your app. If your REST service is written in Java, you can see this question for details on how to add the appropriate headers. Other languages will use a similar mechanism.
My other guess is that the web service requires authorization to access. It works fine from your browser because at one time you provided the proper credentials and
your browser cached them. If your service does require authorization, see the "Setting HTTP Headers" section on this page for information on how to add the appropriate headers.

As Alvin Thompson mentioned, you have to set your access-control-allow origin and should also set your access-control-allow-headers, access-control-allow-credentials on the server side. In my case I had to do this in my WebAPIcontroller. This is because in order for CORS to work (cross-domain) you have to have the service 1 (RESTApi in my case) allow permissions for service 2(client) to receive call it. In order, to allow this I had to add the following NuGet packages
NuGet
- Microsoft.AspNet.Cors NuGet package
- Microsoft.Owin.Cors NuGet package
Once these were installed I went to my config file on the API project and added
API App_Start/WebApiConfig.cs
public static void Register(HttpConfiguration config)
{
config.EnableCors();
}
Then in my controller that inherits the API controller I referenced the NuGet package I installed and enabled CORS on the client side and this is where you set you origin, headers and methods
YourController : ApiController
namespace YourNamespace.Controllers
{
[EnableCors(origins: "https://localhost:.....", headers: "*", methods: "*")]
public class YourController : ApiController
{
//The rest of your controller functionality
}
}
The rest of the issue I was having was how the Json Web Token variable is being passed into my javascript file. I am still working on this, I will post the answer to this as well when I figure it out.
To read more about the CORS issue, this was the best reference for me: http://www.asp.net/web-api/overview/security/enabling-cross-origin-requests-in-web-api

Related

How does restangular talk to MySQL database

I am total JS newbie working on a project build in Grail 2.4.4, a web-app. It's a working app, build by a developer whom is not available anymore.
To get it to work locally I had to upgrade it to Grails 3.2.0. I got it almost working in Netbeans. But I got stuck at getting the data from the MySQL database.
The Chrome inspector says:
angular.min.js GET http://localhost:8080/<app>/currency/allCurrencies 404 ()
The controllers are written in Restangular which call the above URL.
What am I missing?
Firstly, Restangular is an Angular library which simplifies and standardizes making calls to a REST backend (which in your case is a Grails app). So, Restangular does not directly retrieve data from your a database, it invokes a web service which (in some cases) may retrieve data from a database.
In your case, Restangular is attempting to retrieve data from the endpoint http://localhost:8080/<app>/currency/allCurrencies but you are getting a 404 response, indicating that there is no endpoint mapped to this URL.
HTTP REST helps you connect to the API easily. Restangular can handle that by sending standard methods [Get, Post, Delete, Put] to the api like what you see.
This mean StudentController > Get()
localhost:2045/api/student
This mean StudentController > Get(Guid id)
localhost:2045/api/student/8ae37cfa-905b-4c71-ad03-bf416d93bdf8
This mean StudentController > POST(Guid id) ... if you send Post method to the API, it will detect it, this work also on put method
localhost:2045/api/student
use this module to get easily rest api.
Http-Rest-Service

Not able to access protected Web-api after logging in to the default asp.net core web application template

I have used the default web application template for ASP.NET Core and created an application (http://localhost:xxxx/).
Now I have added a new Web API Controller with path as api/test and default get method that returns a test string array and have decorated the API with Authorize attribute.
Now I have run the application and logged in with registered user.
Opened fiddler and tried to access the web API (http://localhost:xxxx/api/test/).
But it's redirecting me to login page. I have tried using the cookie authentication too but still not able to access Web API. Am I missing something here?
[Route("api/test")]
[Authorize]
public class TestController : Controller
{
[HttpGet]
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
}
When you log in from the browser, the browser itself will manage the cookie and use it as part of each subsequent request to the server -- even though you're local this is still the same workflow. You have specified that your entire class is to only accessible to Authorized requested, this means that it will redirect to the login screen if the request doesn't have the correct cookie.
Am I missing something here?
Yes, you're missing that fiddler doesn't know what cookie to use and it's disassociated from the browser. You must instruct fiddler to use the cookie for its request as explained here.

MarkLogic 7 REST API - Bad Request Error

I am building a webapp using AngularJS on top of a MarkLogic 7 XML database. I am using the REST API provided by MarkLogic to access the database. The code I'm using in my controller is as follows.
app.controller("mainController", function($scope, $http){
var addr = 'http://localhost:8011/v1/search?q=test&options=newtest';
$http({method:'GET', url: addr})
.success(function(data){
alert('Success');
console.log(data);
});
});
Now, when I open my view, a 'bad request' error is logged in the console.
OPTIONS http://localhost:8011/v1/search?q=test&options=newtest 400 (Bad Request)
angular.min.js:99
OPTIONS http://localhost:8011/v1/search?q=test&options=newtest No 'Access-Control-Allow-
Origin' header is present on the requested resource. Origin 'null' is therefore not
allowed access. angular.min.js:99
XMLHttpRequest cannot load http://localhost:8011/v1/search?q=test&options=newtest. No
'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'null'
is therefore not allowed access. index.html:1
Are there any settings to be configured on the MarkLogic server to make the API accessible? Please help.
Thanks,
Krishna
Krishna, is your AngularJS code hosted by MarkLogic, or are you running it in node.js (via grunt, perhaps)? This looks like a cross-site scripting problem. Two solutions come to mind:
If you don't need a middle tier, MarkLogic can host the Angular code. Put it in the modules database of the app server on port 8011. Then the request is going to the same place the JS came from and the problem goes away.
If you want to keep a node layer, set up a proxy. Assuming you're using Grunt, you can see how I handled that in the Gruntfile.js of an app with the same stack.
Once you get past that error, you might consider moving the interaction with the MarkLogic REST API into a service. The Demo Cat application I linked to above has an early version of an MLRest AngularJS service; that might be a useful starting point.

Preventing default views with RESTful api in CakePHP

I am following the tutorial in the CakePHP book that explains the basics of setting up a RESTful web service.
So far, I've updated my routes file to the following:
Router::mapResources('stores');
Router::parseExtensions('json');
I have also setup a blank layout in app/layouts/json and the appropriate json views. I am receiving my json output successfully when I navigate to controller/action.json
I am wondering though, without the.json extension it attempts to load the regular view. I am looking to build a pure api with only json output, is there any way to prevent regular render output instead?
You could force a rendering as JSON if you can recognise a JSON request another way. For example, if the Accepts HTTP header contains application/json, you could put this in your controller:
public function beforeFilter(){
if ($this->request->accepts('application/json')) {
$this->RequestHandler->renderAs($this, 'json');
}
parent::beforeFilter();
}
It's CakePHP 2.0 notation, but something similar probably exists for CakePHP 1.2 and 1.3.
You could also detect the request Content-Type instead, or as well, especially if Accepts is not used.
What are you seeing at the moment? If you've used bake Cake may have generated the views for you?
Just delete the views in /app/views/layout and /app/views/controllername
If you are trying to prevent the request from hitting the controller at all then I'm not so sure, you could just update your .htaccess file to only send requests ending in .json to the app or something similar.
here is what i did.
if i know i'm building only json API, i added to my AppController.php following:
public function beforeFilter()
{
if (empty($this->request->params['ext']) || $this->request->params['ext'] != "json")
{
$this->render(FALSE, 'maintenance'); //no view, only layout
$this->response->send();
$this->_stop();
}
}
and in my /app/Layouts/maintenance.ctp
echo __('Invalid extension');
this way all requests without the json extension will end up on the "maintenance" page where you can put any info you want, i'm planning to put there link to API docs.

How can I access auth-only Twitter API methods from a web application

I have a web application for iPhone, which will ultimately run within a PhoneGap application - but for now I'm running it in Safari.
The application needs to access tweets from Twitter friends, including private tweets. So I've implemented OAuth using the Scribe library. I successfully bounce users to Twitter, have them authenticate, then bounce back.
At this point the web app has oAuth credentials (key and token) which it persists locally. From here on I'd like it to user the Twitter statuses/user_timeline.json method to grab tweets for a particular user. I have the application using JSONP requests to do this with unprotected tweets successfully; when it accesses the timeline of a private Twitter feed, an HTTP basic authentication dialog appears in the app.
I believe that I need to provide the OAuth credentials to Twitter, so that my web application can identify and authenticate itself. Twitter recommends doing so through the addition of an HTTP Authorization header, but as I'm using JSONP for the request I don't think this is an option for me. Am I right in assuming this?
My options therefore appear to either be putting the oAuth credentials as query-string parameters (which Twitter recommends against, but documentation suggests still supports); or proxying all the Tweets through an intermediate server. I'd rather avoid the latter.
I access the Twitter API using URLs of the form
http://api.twitter.com/1/statuses/user_timeline.json?user_id=29191439&oauth_nonce=XXXXXXXXXXX&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1272323042&oauth_consumer_key=XXXXXXXXXX&oauth_signature=XXXXXXXXXX&oauth_version=1.0
When user_id is a public user, this works fine. When user_id is a private user, I get that HTTP Basic Auth dialog. Any idea what I'm doing wrong? I'm hoping it's something embarrassingly simple like "forgetting an important parameter"...
The oAuth stanza needs to be exact, as per http://dev.twitter.com/pages/auth#auth-request - I ended up building an Authorization: header that I could first check with curl.
I built it using the really helpful interactive request checker at http://hueniverse.com/2008/10/beginners-guide-to-oauth-part-iv-signing-requests/
Here's a friends API request for a protected user:
curl -v -H 'Authorization: OAuth realm="https://api.twitter.com/1/friends/ids.json", oauth_consumer_key="XXXXXXXXXXXXXXXX", oauth_token="XXXXXXXXXXXXXXXX", oauth_nonce="XXXXXXXXXXXXXXXX", oauth_timestamp="1300728665", oauth_signature_method="HMAC-SHA1", oauth_version="1.0", oauth_signature="XXXXXXXXXXXXXXXX%3D"' https://api.twitter.com/1/friends/ids.json?user_id=254723679
It's worth re-iterating that as you've tried to do, instead of setting the Authorization header via e.g. jquery's beforeSend function, that for cross-domain JSONP requests (which can't add HTTP headers) you can make oAuth requests by putting all the relevant key/value pairs in the GET request. This should hopefully help out various other questioners, e.g
Set Headers with jQuery.ajax and JSONP?
Modify HTTP Headers for a JSONP request
Using only JQuery to update Twitter (OAuth)
Your request looks like it has a couple of problems; it's missing the user's oauth_token plus the oauth_signature doesn't look like it has been base64 encoded (because it's missing a hex encoded = or ==, %3 or %3D%3D respectively).
Here's my GET equivalent using oAuth encoded querystring params, which you can use in a cross-domain JSONP call:
https://api.twitter.com/1/friends/ids.json?user_id=254723679&realm=https://api.twitter.com/1/friends/ids.json&oauth_consumer_key=XXXXXXXXXXXXXXXX&oauth_token=XXXXXXXXXXXXXXXX&oauth_nonce=XXXXXXXXXXXXXXXX&oauth_timestamp=1300728665&oauth_signature_method=HMAC-SHA1&oauth_version=1.0&oauth_signature=XXXXXXXXXXXXXXXX%3D
I was struggling with similar problem of making JSONP requests from Jquery, the above answer helped just to add what I did to achieve my solution.
I am doing server to server oauth and then I send oauth token, secret, consumer key and secret (this is temporary solution by the time we put a proxy to protect consumer secret). You can replace this to token acquiring code at client.
Oauth.js and Sha1.js download link!
Once signature is generated.
Now there are 2 problems:
JSONP header cannot be edited
Signed arguments which needs to be sent as part of oauth have problem with callback=? (a regular way of using JSONP).
As above answer says 1 cannot be done.
Also, callback=? won't work as the parameter list has to be signed and while sending the request to remote server Jquery replace callback=? to some name like callback=Jquery1232453234. So a named handler has to be used.
function my_twitter_resp_handler(data){
console.log(JSON.stringify(data));
}
and getJSON did not work with named function handler, so I used
var accessor = {
consumerSecret: XXXXXXXXXXXXXXXXXXXXXX,
tokenSecret : XXXXXXXXXXXXXXXXXXXXXX
};
var message = { action: "https://api.twitter.com/1/statuses/home_timeline.json",
method: "GET",
parameters: []
};
message.parameters.push(['realm', "https://api.twitter.com/1/statuses/home_timeline.json"]);
message.parameters.push(['oauth_version', '1.0']);
message.parameters.push(['oauth_signature_method', 'HMAC-SHA1']);
message.parameters.push(['oauth_consumer_key', XXXXXXXXXXXXXXXX]);
message.parameters.push(['oauth_token', XXXXXXXXXXXXXXX]);
message.parameters.push(['callback', 'my_twitter_resp_handler']);
OAuth.completeRequest(message, accessor);
var parameterMap = OAuth.getParameterMap(message.parameters);
Create url with base url and key value pairs from parameterMap
jQuery.ajax({
url: url,
dataType: "jsonp",
type: "GET",
});