AngularJS giving 404 error on first run - javascript

I have written a very basic AngularJS script to parse JSON response. When I run this, I get a 404 status (error), while it works fine after that. I have been able to replicate this behavior on Google chrome and Opera while it works fine on Firefox.
What could be the problem?
<body ng-app="myApp" ng-controller="FormCtrl">
<form name="saveTemplateData" action="#">
First name:<br/>
<input type="text" ng-model="form.firstname"><br/><br/>
<input type="text" ng-model="form.firstname1">
<input type="submit" id="submit" value="Submit" ng-click="submitForm()" />
</form>
<ul>
<li ng-repeat="friend in friends">
{{friend.name}}, {{friend.house_no}}
</li>
</ul>
<script src="angular.min.js"></script>
<script src = "step4.js"></script>
</body>
</html>
The controller is as follows:
var app = angular.module('myApp', []);
app.controller('FormCtrl', function ($scope, $http) {
$scope.formData = {
firstname: "default",
firstname1: "default"
};
$scope.save = function () {
formData = $scope.form;
};
$scope.submitForm = function () {
console.log("posting data....");
$scope.formData = $scope.form;
$http({
method: 'GET',
url: 'http://localhost/testjson.php',
params: {
firstname: $scope.formData.firstname,
firstname1: $scope.formData.firstname1
}
}).success(function (data) {
//var pretty;
$scope.friends = data.response.docs;
//angular.toJson(data, [pretty]);
var str = JSON.stringify(data, undefined, 2);
//document.write(str);
alert("success");
}).error(function (data, status, headers, config) {
alert(status);
});
};
});
The PHP file just returns a dummy JSON file
<?php
header('Content-Type: application/json');
header("Access-Control-Allow-Origin: *");
$state = $_GET['firstname'];
$state1 = $_GET['firstname1'];
$arr = '{
"response": {
"numFound": 1,
"start": 0,
"docs": [
{
"name": "'.$state.'",
"house_no": "76"
}
]
}
}';
echo $arr;
?>
EDIT:
Some further Problem Diagnosis:
The problem is with both local and global URLs (working URLs with cross domain access allowed)
When I enter a value in textbox and submit, a 404 error is received and the page is refreshed. But if I re-submit the form again with the same information the results are shown. This probably means that the results are fetched but somehow a 404 error is shown in the first execution of get request. Since, above is the entire code I have, I am not able to determine where the problem lies.
There are no errors in the console. In the network tab, following details are there
Method:GET
Status: Cancelled
Initiater: angular.js:8081
Time:Pending

Are you serving the html/js from the filesystem?
i.e. file:///angular-test.html
If so you might be hitting a cross origin problem. See this other question about angular and 404s for a possible answer.

You are running this locally, correct? You need to add a port to your localhost, in the HTTP call in the controller:
(protocol)://localhost:XXXX/
MAMP/LAMP is usually port 8888 (your PHPs stack)
Cheers and <3 angular

Most of the tutorials on angularJS seem to leave the action field empty, but rather it turned out that action field is not required at all.
The issue is with the line
<form name="saveTemplateData" action="#">
It should rather be
<form name="saveTemplateData">
Additional help received from AngularJS Github issue.

Related

vue + nuxt.js - How to read POST request parameters received from an external request

I have a an external form which submits a post request to my nuxt app. I am struggling currently to find out how I can access these POST request parameters in my nuxt page?
I found so far the "asyncData" method, but when I try to access the submitted parameter through the "params" object it is always "undefined". What do I wrong here?
"asyncData" nuxt reference
example code in my nuxt page, assuming "email" is the request parameter submitted from outside
export default {
asyncData({ params }) {
console.log('asyncData called...' + params.email);
return {email: params.email};
},
external html form
<body>
<form action="https://..." target="_blank" method="post">
<input name="email" class="input" type="text" placeholder="Email" maxlength="255"></input>
<input name="submit" class="btn" type="submit" value="Ok"></input>
</form>
</bod>
I found a way, as described in "asyncData" nuxt reference you can pass the request and response object to the "asyncData({req,res})" call.
Here an example - assuming 'email' is one of the post parameter. querystring is a module of node.js and allows you to parse the request body into an array.
Small Remark - this seems only to work for nuxt page level components but not for lower level components
<script>
export default {
asyncData({ req, res }) {
if (process.server) {
const qs = require('querystring');
var body = '';
var temp = '';
while(temp = req.read()) {
body += temp;
}
var post = qs.parse(body);
return {data: post};
}
},
data() {
return {
data: '',
}
},
mounted() {
console.log(this.data['email']);
},
</script>
Nuxt.js cannot handle such things by itself.
https://nuxtjs.org/api/configuration-servermiddleware
You should implement your own middleware for such cases.
And asyncData has nothing to do with handling inbound POST data.

Laravel Ajax 419 Error on Production but not Local Development and Nothing In /storage/logs/laravel.log

So I've run into this issue where I'm having a 419 Error code when submitting my AJAX request through my project. I know that this error is due to the CSRF Token not being passed, or not valid.
Story behind this: I've created a "maintenance mode" on my project. This maintenance mode restricts access to the front end by displaying the 503 error page, but still allows my administrators access to the backend to update the site, etc. This is done using some middleware. See the code here on my github page for more information on how I accomplish this functionality.
https://github.com/JDsWebService/ModelAWiki/commit/263a59ebba42688d4a232a5838334b9ee419504c
So maybe this is an issue with the 503 error page on my production environment? I'm not too sure.
I've taken a look at this Question and Answer on SOF, but it doesnt seem to be helping me any.
Laravel 5.5 ajax call 419 (unknown status)
Here is the production site, take a look at the console for more information: http://modelawiki.com/
Here is my code pertaining to the 419 error:
Javascript
$(document).ready(function() {
// CSRF Ajax Token
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
// Add Section Post Button
$('#subscribeButton').click(function(event) {
/* Act on the event */
// Clear Feedback Boxes
$('#valid-feedback').css("display", "none");
$('#invalid-feedback').css("display", "none");
// Input Field
var email = $('#email').val();
var token = $('meta[name="csrf-token"]').attr('content');
console.log(email);
console.log(token);
// Post
$.ajax({
type: 'POST',
url: '/email/subscribe/',
dataType: 'json',
data: {
email: email,
"_token": token,
},
success: function (data) {
// Check Server Side validation
if($.isEmptyObject(data.errors)){
// Show the Feedback Div
$('#valid-feedback').css("display", "block");
// Add the Bootsrapt Is Invalid Class
$('#email').addClass('is-valid');
// Validation Failed Display Error Message
$('#valid-feedback').text(data['success']);
// Animate the Object
$('#email').animateCss('tada', function() {});
console.log(data['success']);
}else{
// Show the Feedback Div
$('#invalid-feedback').css("display", "block");
// Add the Bootsrapt Is Invalid Class
$('#email').addClass('is-invalid');
// Validation Failed Display Error Message
$('#invalid-feedback').text(data.errors[0]);
// Animate the Object
$('#email').animateCss('shake', function() {});
console.log(data.errors);
}
},
error: function (data) {
console.log(data);
}
}); // End Ajax POST function
}); // End Click Event
// On Focus of the Email Box
$('#email').focus(function(event) {
/* Act on the event */
$('#valid-feedback').css("display", "none");
$('#invalid-feedback').css("display", "none");
});
}); // End Document Ready
HTML Form
<div class="input-group input-group-newsletter">
<input type="email" class="form-control" placeholder="Enter email..." aria-label="Enter email..." aria-describedby="basic-addon" id="email">
<div class="input-group-append">
<button class="btn btn-secondary" type="button" id="subscribeButton">Notify Me!</button>
</div>
<div id="invalid-feedback" class="invalid-feedback"></div>
<div id="valid-feedback" class="valid-feedback"></div>
</div>
Header (This shows that the CSRF token is actually on the 503 error page)
<meta name="csrf-token" content="{{ csrf_token() }}">
Again, this code works on my local environment, but not on my production environment. (I also know that AJAX requests can and are being handled in other parts of my site just fine on the production environment, so I know it's not a server issue and has to do with code)
Just in case here is my controller code as well.
// Store the Email into the database
public function subscribe(Request $request) {
// Validate the request
$validator = Validator::make($request->all(), [
'email' => 'required|email|max:255|unique:email_subscribers,email',
]);
// If the validation fails
if($validator->fails()) {
return response()->json([
'errors' => $validator->errors()->all(),
]);
}
// New Section Object
$subscription = new EmailSubscription;
// Add Name into Section Object
$subscription->email = $request->email;
// Save the Section
$subscription->save();
// Return The Request
return response()->json([
'success' => 'You have successfully subscribed! Check your email!'
]);
}
And my route
// Email Routes
Route::prefix('email')->group(function() {
// Create Post Route for subscribing
Route::post('/subscribe', 'EmailSubscriptionsController#subscribe')->name('email.subscribe');
});
Just in case it can help someone, we experienced the same issue and it was due to a server space disk issue. Therefore, Laravel was unable to write files (sessions.php notably).

Posting Input value as param to web service API in Angular

I have started learning Angular and I'm stuck on something that should be trivial. I'm from a Rails background and created a very simple Rails web-service that manages a MailingList. Currently 2x API endpoints exist in my web-service:
/api/v1/mailing_lists [GET]
/api/v1/mailing_lists [POST]
The POST endpoint requires a valid email as a PARAM in the API call. And this is where I'm stuck. How do I pass this param to my API in Angular? I've tried using solutions from around the web but I'm just not getting it right. Here's what I have thus far:
In my services.js:
angular.module('webFrontendApp.services', []).factory('MailingList', function($resource) {
var data = $resource(
'http://localhost:3000/api/v1/mailing_lists.json',
{},
{
// 'get': { method:'GET', cache: false},
'query': { method:'GET', cache: false, isArray:true },
'save': {method: 'POST', cache: false }
});
return data;
});
In app.js
....
.when('/list/new', {
templateUrl: 'views/list-new.html',
controller: 'MailingListCtrl'
})
....
Controller as mailinglist.js
angular.module('webFrontendApp.controllers', [])
.controller('MailingListCtrl', function($scope, MailingList) {
// Get all posts
$scope.mailing_lists = MailingList.query();
// Our form data for creating a new post with ng-model
$scope.memberData = {};
$scope.newMember = function() {
var member = new MailingList($scope.memberData);
member.$save();
};
});
The form looks like this:
<form role="form" ng-submit="newMember()">
<div class="row">
<div class="input-group">
<input type="text" ng-model="memberData.email" placeholder="New mailing list member" class="form-control">
<span class="input-group-btn">
<input type="submit" class="btn btn-primary" value="Add">
</span>
</div>
</div>
</form>
When I submit the form, nothing seems to happen, but I am receiving a 405 error response from my web service. After looking into my Web Service logs, I can see that a POST request was received but no params were passed and thus it was rejected.
Any help will be greatly appreciated!
PS. I have made sure to Enable CORS on my Rails app.
Pass params inside $save method, pass post_data inside MailingList, so basically this should work
$scope.newMember = function() {
var member = new MailingList();
member.$save({email: $scope.memberData.email});
};

Angular http request with custom data

I am trying to do a http request to a php file on my server. My code i am using at the moment is as follows:
App.controller('GetSales', ['$scope', '$http', function ($scope, $http) {
$http({
method: 'POST',
url: '/app/controller/apis/_sales.php?period_start=2015-07-01&period_end=2015-07-31&join=leads&status=0&category=0user=1'
})
.success(function (data) {
$scope.sales = data;
});
}]);
Isnt there a better way to do this?
When i add these var as data it doesnt get posted to my page?
data: {
period_start: '2015-07-01',
period_end: '2015-07-31',
join: 'leads',
status: '',
category: '',
user: '1'
};
In php i get the data like this, its also sanitized for security reason:
$user = filter_var($_REQUEST['user'], FILTER_SANITIZE_NUMBER_INT);
$period_start = $_REQUEST['period_start'].' 00:00:00';
At first sight you are tryng to call an HTTP POST service, but you send parameter like it was a GET service, try something like that:
App.controller('GetSales', ['$scope', '$http', function ($scope, $http) {
$http.post('/app/controller/apis/_sales.php',
{
period_start: '2015-07-01',
period_end: '2015-07-31',
join: 'leads',
status: '',
category: '',
user: '1'
})
.success(function (data) {
$scope.sales = data;
})
.error(function (data, status) {
console.log(status);
});
I would use json_decode( file_get_contents('php://input') ) on your serverside. Also, please don't forget to sanitize your user sent data!
var dataParams = {
period_start: '2015-07-01',
period_end: '2015-07-31',
join: 'leads',
status: '',
category: '',
user: '1'
};
App.controller('GetSales', ['$scope', '$http', function ($scope, $http) {
$http.post('/app/controller/apis/_sales.php', dataParams)
.success(function (data) {
$scope.sales = data;
});
}]);
You will want to watch ever using the variable data as it will most likely collide with another variable, such as in your demonstration where you have named your post params as data while the return response is also aliased as data in the $.post success. This may not cause an issue in this case - but it usually will, so I renamed it for you out of habit.
Your server side could look something like this depending on what your usernames strings consist of:
public static function sanatize_client_string($dirtyString){
$cleanString = htmlspecialchars(strtolower(preg_replace("/[^a-z]+/i", "[FORBIDDEN_CHAR]", $dirtyString)));
return $cleanString;
}
$client_data = sanatize_client_string(json_decode( file_get_contents('php://input')));
Now you can access the username like:
echo $client_data['user']; // Will echo 1 based on the post data you are sending
This is what a simple serverside data-router could look like, as using normal $_POST has never worked for Angular data for me either:
/**
* Collect all Angular HTTP Request data
*/
$client_data = json_decode( file_get_contents('php://input') );
$app_state = utils::sanatizeClientString($client_data->appState); // <- name of prop must match client angularPostObj.x = serverModel.x
/**
* Cache the view path to the model
*/
$module_exists_in_model = isset($app['view_data']['views'][$app_state]);
/**
* If the angular post request matches data in the model, return the requested dataset, while if no object is found
* under that address, the error object will be returned which will send and error data to the view.
*
* This error condition will never happen aside from an attack because the clientside AngularJS router would prevent any
* unregistered paths from being even sent to the server. This would happen using a post mocking service or by
* forcing the string change in the code inspector while using the site.
*/
$module_exists_in_model ?
$view_model = $app['view_data']['views'][$app_state] :
$view_model = $app['view_data']['views']['error'];
// Call the view from Angular post data, passing it to a Class that sends a response as valid JSON
Render_app::echo_json($view_model);
I was informed of this by: http://www.cleverweb.nl/javascript/a-simple-search-with-angularjs-and-php/ and How to post a data in Angular?.
The point is... use $client_data = json_decode( file_get_contents('php://input') ); instead of $client_data = $_POST['username'];

Can't delete objects with angular.js

I have defined myself an api for use with Angular.js:
angular.module('api', ['ngResource'])
.factory('Server', function ($resource) {
return $resource('http://localhost\\:3000/api/servers/:name');
})
.factory('ActiveServer', function ($resource) {
return $resource('http://localhost\\:3000/api/servers/active/:name', {},
{ start: {method: 'POST'}, stop: {method: 'DELETE'} });
});
The idea, is that I have a set of defined servers, available through the /api/servers/ uri. A particular server can be started by adding it to the /api/servers/active/ uri, and stopped by deleting it.
In my controller, I have the following code:
$scope.start = function() {
ActiveServer.start(this.server);
};
$scope.stop = function() {
ActiveServer.stop(this.server);
};
which again is triggered by buttons
<div class="well span4" ng-repeat="server in servers">
<h1>{{server.definition.name}}</h1>
<span class="label label-info">{{server.status}}</span>
<button type="button" class="btn btn-primary"
ng-click="start()">Start</button>
<button type="button" class="btn btn-primary"
ng-click="stop()">Stop</button>
</div>
Starting the server works alright, but I have trouble stopping it. The code above ends up with the following request:
Request URL:http://localhost:3000/api/servers/active?$$hashKey=005&_events=[object+Object]&definition=[object+Object]&status=ready
Request Method:DELETE
The definition-part of my server object, containing the name that identifies the server to stop, isnĀ“t serialized right.
How can I fix this?
If your API (ActiveServer) only needs to receive the server's name to work, then pass only the server's name during the service call. Like this:
$scope.start = function() {
ActiveServer.start({name: this.server.definition.name});
};
$scope.stop = function() {
ActiveServer.stop({name: this.server.definition.name});
};
Passing the entire this.server object in any service call will result on the entire object being parametrized into the HTTP request.
extended explanation:
When you use something like api/servers/:name on your $resource URL, you are basically saying that the :name part will be replaced by the value of a property with the same name (in this case, 'name') received on the parameters (i.e. {name: 'someName'}).
From the angularJS $resource documentation:
Each key value in the parameter object is first bound to url template
if present and then any excess keys are appended to the url search
query after the ?. Given a template /path/:verb and parameter
{verb:'greet', salutation:'Hello'} results in URL
/path/greet?salutation=Hello. If the parameter value is prefixed with
# then the value of that parameter is extracted from the data object
(useful for non-GET operations).
So, if you call service.get({name: 'abc'}) then URL of the request will be
api/server/abc
If you call service.get({name: 'abc', id: '123'}) then URL will be api/server/abc?id=123
In your case, the this.server Object looks something like this:
{
$$hashKey: 005,
_events: {},
definition: {},
status: ready
}
Since AngularJS does not do in-depth parametrization, _events and definitions are shown as _events=[object+Object]&definition=[object+Object] on the URL.

Categories

Resources