When I create a new Google Cloud function, the default code given is:
const functions = require('#google-cloud/functions-framework');
functions.http('helloHttp', (req, res) => {
res.send(`Hello ${req.query.name || req.body.name || 'World'}!`);
});
However, in this tutorial, the function is specified as:
exports.validateTemperature = async (req, res) => {
try {
if (req.body.temp < 100) {
res.status(200).send("Temperature OK");
} else {
res.status(200).send("Too hot");
}
} catch (error) {
//return an error
console.log("got error: ", error);
res.status(500).send(error);
}
};
What is the difference between the two? How do they work in the bigger scheme of things?
In the second example, the code is listening for a Http POST request. Where is this specified?
Through the two methods you exposed the result is the same, a HTTP Path is used to receive the Request and Response objects.
Inside the Request object, you may find the Body (usually filled in POST & PUT requests but not limited to) and the Method (GET, POST, PUT, etc).
Therefore, your Cloud Function code will be used with both a GET and a POST call in either solution.
Functions Framework
Functions Framework turns a Cloud Functions snippet into a workable server. It's kind of like register a handler function to an express router, and run the express app behind the scenes.
The main use case is local development and migrant to App Engine or other services. They both need to start a HTTP server, and functions framework does that.
Express
Node.js runtime explains your code snippet using Express framework.
The validateTemperature accepts all HTTP methods.
We often filter HTTP methods by a router. Although you can do it in with req.method. And router, web server level is what you don't want to reapeat again and again.
If you want to split requests by method when buiding an API service, you could consider let Cloud Endpoints or some API Gateway stands before your functions.
I am working on a webapp built upon angularjs.So,i have a search result UI built which upon search displays result in grid.Now,when user clicks on each row of the result ,an external webpage should be called with values of columns passed from that clicked grid row to the external webpage.
How can i do this,can i have a sample controller to refer upon.
Please help with this
Thanks,
Alex
If I understand you correctly, you want to send an AJAX call to some JSON api when a user clicks on some element. Here's a basic thing of how to do that in an angularjs controller:
angular.module("your.app")
.controller("ajaxingCtrl",["$http","$scope", function($http, $scope){
$scope.onSomeUserAction = function(argument){
//substitute the type of request your api requires
$http.get("http://your.remote.api/some/resource",
{
//params will get parsed into HTTP query parameters
params: {
x:arguments.x
}
}
).then(function(result){
console.log(result);// and then do what you will with the result
})
}
}])
You can find more information about doing ajax calls in angular's $http service docs.
I have a headless application written in yii, with an Angular application using the yii2 api. Currently im using local storage for tokens, but I read this link and would like to store the token in a cookie.
Auth action:
\Yii::$app->response->cookies->add(new Cookie([
'name' => 'token',
'value'=> $token->__toString()
]));
AuthMethod:
if (($cookie = $cookies->get('token')) !== null) {
die('Token found in cookie');
$token = $parser->parse($cookie->value);
}
The token is allways null, so it seems like cookies are disabled by default in Rest controllers / JSON responses, how can I enable this?
For furture reference, if the link is dead it concludes that cookies are better than local storage for JWT tokens
Cookies, when used with the HttpOnly cookie flag, are not accessible through JavaScript, and are immune to XSS. You can also set the Secure cookie flag to guarantee the cookie is only sent over HTTPS. This is one of the main reasons that cookies have been leveraged in the past to store tokens or session data. Modern developers are hesitant to use cookies because they traditionally required state to be stored on the server, thus breaking RESTful best practices. Cookies as a storage mechanism do not require state to be stored on the server if you are storing a JWT in the cookie. This is because the JWT encapsulates everything the server needs to serve the request.
EDIT
Using the native PHP $_COOKIE the cookie can be read by the yii2 application, but the setcookie() does not work. It looks like the yii2-rest controller strips away the headers before sending the response.
I will make my first attempt to answer and I hope it makes sense and helps you and others.
I asked you about angular version, because, as you know angular works as a one page app, and I will need proof of concept code to show my point «I will asume angularjs 1.6.x», it means it works away from your YII2, unless you are rendering angular on call. Now there are two ways to “bypass” this in order to set up the cookie.
The first one will be to set up your cookie inside angular, on your controller call your login endpoint and make it return the token (in my example I am not doing that part just for speed). And then build the cookie using the $cookie service «you will have to import angular-cookie».
The other way could be to call and endpoint inside Yii «look at the actionSetCookie example» and build the cookie inside it, I don't like that one that much looks dirty to me.
Now here comes the big problem, you may have, yii uses a cookie validation that “signs the cookie”, but when you build the cookie outside, this cookie will not work. So… to make this example work you will have to turn off cookie validation.
components' => [
'request' => [
'enableCookieValidation' => false, //<---make it false
'enableCsrfValidation' => true,
'cookieValidationKey' => 'hdfghdsrthrgfdhfghthdrtth',
'parsers' => [
'application/json' => 'yii\web\JsonParser',
]
],
...
]
Now, I made a working test.
First I made two simple action to test that I was actually building the cookie. And that I was able to call them with postman.
public function actionSetCookie()
{
Yii::$app->response->format = Response::FORMAT_JSON;
$session = Yii::$app->session;
$cookies_rsp = Yii::$app->response->cookies;
$cookies_rsp->add(new Cookie([
'name' => 'token',
'value' => 'tt-eyJhbGciOiJIUzI1NiIs...',
]));
$response = ['cookie set'=>$cookies_rsp];
return $response;
}
public function actionCookie()
{
Yii::$app->response->format = Response::FORMAT_JSON;
$session = Yii::$app->session;
$cookies = Yii::$app->request->cookies;
$token = '';
if (isset($cookies['token'])) {
$token = $cookies['token']->value;
}
$response = ['token'=>$token];
return $response;
}
And I made two controllers in angular to make the explanation:
.controller('View1Ctrl', ['$cookies', function ($cookies) {
console.log('View1Ctrl++++++++');
var vm = this;
vm.title = 'Customers';
$cookies.remove('token');
$cookies.put('token', 'my-angular-token');
vm.myToken = $cookies.get('token');
console.log('myToken', vm.myToken);
}
.controller('View2Ctrl', ['$http', function ($http) {
console.log('View2Ctrl');
//Lest set the cookie
$http({
method: 'GET',
url: 'http://test.dev/site/set-cookie'
}).then(function successCallback(response) {
console.log('response', response);
}, function errorCallback(response) {
console.error('err', response)
});
}
Now here it goes
On solution 1 «View1Ctrl», I build the cookie using the $cookie service, and I can validate it using action actionCookie, this will be read only if enableCookieValidation is false.
On the solution 2 «View2Ctrl», I am using the actionSetCookie as a http get endpoint that does not much, but sets the cookie, this cookie will work with enableCookieValidation false or true.
Conclusión
Remember that angular and yii2 are "supposed" to be agnostic and independent, so you will have to consume yii as endpoint.
You will have to se the enableCookieValidation, depending on your solution. I am not sure if there is a way to do it with angular but probably is not a good idea because you will have to publish the cookieValidationKey inside angular.
I don't like using cookies for apis, personally, because the idea of stateless and cookieless will help if your are developing a mobile app «I might be wrong about that».
About postman, it will work with solution 2 unless you turn off enableCookieValidation. Remember that this validation will add some salt to the token inside a cookie, that is yii additional security.
Finally on p[ostman, if enableCookieValidation is set to true and toy are manually making the cookie, Yii will not receive the cookie, because of security.
Just to illustrate this security related to the signing of cookies, I captured this video. I hope this will help. So this is because CookieValidation is true. This is a reason no to use the PHP default cookie service but tu use the one that Yii provides. On the video you will see how this system very specific for each cookie. ANd why you may not see the cookie in postman.
If you make CookieValidation false, this manual cookies, php default cookies will actually work again, but is less secure.
Video
About the discussion on the blog and Angular, remember that angular actually protects your app when using $http calls, it is very secure in that sense, but also don't forget to use ngSanitize on your app.
More on this:
https://docs.angularjs.org/api/ng/service/$http#cross-site-request-forgery-xsrf-protection
https://docs.angularjs.org/api/ngSanitize
https://docs.angularjs.org/api/ngCookies/service/$cookies
Finally, if I find something on securing the cookie like Yii2 does from angular I will add that to the post.
Hope it helps.
Just in case you like to look at my code
https://github.com/moplin/testdev
If you want to access cookies on server side so you have to send them as well in your request. Angular by default does not send cookies in XHR request. To enable cookies in request add this following code:
.config(function ($httpProvider) {
$httpProvider.defaults.withCredentials = true;
});
OR
$http.get("URL", { withCredentials: true })
.success(function(data, status, headers, config) {})
.error(function(data, status, headers, config) {});
See Usage section in angular $http
Make sure you also setting that cookie on client side, using javascript and then check in your chrome console for http request making sure it's also sending cookie in it.
Make sure you read cookies from $cookies = Yii::$app->request->cookies;
http://www.yiiframework.com/doc-2.0/guide-runtime-sessions-cookies.html#reading-cookies
And writing a cookie using $cookies = Yii::$app->response->cookies;
http://www.yiiframework.com/doc-2.0/guide-runtime-sessions-cookies.html#sending-cookies
If the token is an access token you could you use in REST controller
the autheticator behaviors
yii\filters\auth\HttpBasicAuth;
yii\filters\auth\HttpBearerAuth;
yii\filters\auth\QueryParamAuth;
and when received first time token to save it to a cookie in the browser from angular
I've just created a project for working with REST API (using yii2 framework).
All issues of REST API is working really cool on localhost. But when bringing the project on server (also the same database is taken by), the authorization is not available. Now I'm using "yii\filters\auth\HttpBearerAuth"
Inside the model "implements IdentityInterface", there's finding-token function "findIdentityByAccessToken" that's so simple, the "validateAuthKey" function is returning always true; see below:
public static function findIdentityByAccessToken($token, $type = null){
return static::findOne(["token" => $token]);
}
public function validateAuthKey($token)
{
return true;
}
See any pictures:
https://www.flickr.com/photos/40158620#N03/20701523349/in/dateposted-public/
Anyone can have some experience on this problem, can you tell me how to solve it? Thanks for your kindness.
Note:
The project, I'm following https://github.com/NguyenDuyPhong/yii2_advanced_api_phong (It works fine on localhost; I also deployed exactly the project on my server, it raised the same problem )
To make sure that the server is configured right: I created 2 actions, 1 is authorized, another is not. I checked unauthorized action, it works very well. =======>
actionView is not authorized => getting API info. is ok
actionIndex is authorized by "yii\filters\auth\HttpBearerAuth" => FAIL
In my case the Problem was that the server removes Authorization Header
I needed to add this to .htaccess
SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1
HttpBearerAuth used $user->loginByAccessToken to authorize see
validateAuthKey used by "loginByCookie"(and it seems that in this case not used)
Try to use QueryParamAuth for test purposes (it's easier to test)
My website is a posting site with posts from different countries. On homepage load i will make a service call and get all the posts using a controller($http) and will be displayed on the homepage.
In the homePage two dropdown and a button are given from which user can choose or filter the posts by country and theme, and results will be in different page.
I want to use the same controller response data without making a new service call to filter the response and show the results.
Please help me on how can i use the same controller or do i need to use a factory and then make the factory as a dependent to my controller??
The best way to do that is to do with a Service. Service is a Singleton, which means that construction will happen only once. In Service constructor you will load posts, and the from any controller you can access your data.
angular.module('myApp').service('myPostService', function($http) {
var Service = {
postList: []
};
// Here load over $http service your posts and then put it into Service.postList.
return Service;
});
Then inject the service and use the posts
angular.module('myApp').controller('HomeCtrl', function(myPostService) {
$scope.postList = Service.postList;
});
And in HTML iterate over it, filter and do whatever you want.