Giter Site home page Giter Site logo

vrata's Introduction

vrata

Build Status Latest Stable Version Code Climate Test Coverage Total Downloads License

Docker Hub

API gateway implemented in PHP and Lumen. Currently only supports JSON format.

Preface

API gateway is an important component of microservices architectural pattern – it's a layer that sits in front of all your services. Read more

Overview

Vrata (Russian for 'gates') is a simple API gateway implemented in PHP7 with Lumen framework

Introductory blog post in English, in Russian

Requirements and dependencies

  • PHP >= 7.0
  • Lumen 5.3
  • Guzzle 6
  • Laravel Passport (with Lumen Passport)
  • Memcached (for request throttling)

Running as a Docker container

Ideally, you want to run this as a stateless Docker container configured entirely by environment variables. Therefore, you don't even need to deploy this code anywhere yourself - just use our public Docker Hub image.

Deploying it is as easy as:

$ docker run -d -e GATEWAY_SERVICES=... -e GATEWAY_GLOBAL=... -e GATEWAY_ROUTES=... pwred/vrata

Where environment variables are JSON encoded settings (see configuration options below).

Configuration via environment variables

Ideally you won't need to touch any code at all. You could just snap the latest Docker image, set environment variables and done. API gateway is not a place to hold any business logic, API gateway is a smart proxy that can discover microservices, query them and process their responses with minimal adjustments.

Terminology and structure

Internal structure of a typical API gateway - microservices setup is as follows:

API gateway - structure

Since API gateway doesn't have any state really it scales horizontally very well.

Lumen variables

CACHE_DRIVER

It's recommended to set this to 'memcached' or another shared cache supported by Lumen if you are running multiple instances of API gateway. API rate limitting relies on cache.

DB_DATABASE, DB_HOST, DB_PASSWORD, DB_USERNAME, DB_CONNECTION

Standard Lumen variables for your database credentials. Use if you keep users in database. See Laravel/Lumen documentation for the list of supported databases.

APP_KEY

Lumen application key

Gateway variables

PRIVATE_KEY

Put your private RSA key in this variable

You can generate the key with OpenSSL:

$ openssl genrsa -out private.key 4096

Replace new line characters with \n:

awk 1 ORS='\\n' private.key

PUBLIC_KEY

Put your public RSA key in this variable

Extract public key using OpenSSL:

$ openssl rsa -in private.key -pubout > public.key

Replace new line characters with \n:

awk 1 ORS='\\n' public.key

GATEWAY_SERVICES

JSON array of microservices behind the API gateway

GATEWAY_ROUTES

JSON array of extra routes including any aggregate routes

GATEWAY_GLOBAL

JSON object with global settings

Logging

Currently only LogEntries is supported out of the box. To send nginx and Lumen logs to LE, simply set two environmetn variables:

LOGGING_ID

Identification string for this app

LOGGING_LOGENTRIES

Your user key with LogEntries

Features

  • Built-in OAuth2 server to handle authentication for all incoming requests
  • Aggregate queries (combine output from 2+ APIs)
  • Output restructuring
  • Aggregate Swagger documentation (combine Swagger docs from underlying services) *
  • Automatic mount of routes based on Swagger JSON
  • Sync and async outgoing requests
  • DNS service discovery

Installation

You can either do a git clone or use composer (Packagist):

$ composer create-project poweredlocal/vrata

Features

Auto-import of Swagger-compliant endpoints

You can define URL(s) of Swagger documentation endpoints - a default URL and custom per-service URLs if necessary. Imagine you have a Symfony2 microservice with Nelmio ApiDoc plugin running on /api/doc. Your microservice returns something like:

$ curl -v http://localhost:8000/api/doc
{
	"swaggerVersion": "1.2",
	"apis": [{
		"path": "\/uploads",
		"description": "Operations on file uploads."
	}],
	"apiVersion": "0.1",
	"info": {
		"title": "Symfony2",
		"description": "My awesome Symfony2 app!"
	},
	"authorizations": []
}

$ curl -v http://localhost:8000/api/doc/uploads
{
	"swaggerVersion": "1.2",
	"apiVersion": "0.1",
	"basePath": "\/api",
	"resourcePath": "\/uploads",
	"apis": [{
		"path": "\/uploads",
		"operations": [{
			"method": "GET",
			"summary": "Retrieve list of files",
			"nickname": "get_uploads",
			"parameters": [],
			"responseMessages": [{
				"code": 200,
				"message": "Returned when successful",
				"responseModel": "AppBundle.Entity.Upload[items]"
			}, {
				"code": 500,
				"message": "Authorization error or any other problem"
			}],
			"type": "AppBundle.Entity.Upload[items]"
		}
	},
	"produces": [],
	"consumes": [],
	"authorizations": []
}

This endpoint may be auto-imported to API gateway during container start (or whenever you see it fit).

Assuming this microservice is listed in GATEWAY_SERVICES, we can now run auto-import:

$ php artisan gateway:parse                                                                                                                                              
** Parsing service1                                                                                                                                                         
Processing API action: http://localhost:8000/uploads                                                                                                                
Dumping route data to JSON file                                                                                                                                          
Finished!                                                                       

That's it - Vrata will now "proxy" all requests for /uploads to this microservice.

OAuth2 authentication

Vrata ships with Laravel Passport - a fully featured OAuth2 server. JSON Web Tokens are used to authenticate all API requests, and currently only local persistence (database) is supported. However, it's trivial to move OAuth2 server outside and rely on JWT token verification using public keys.

If incoming bearer token is invalid, Vrata will return 401 Non Authorized error. If the token is valid, Vrata will add two extra headers when making requests to underlying microservices:

X-User

Numeric subject Id extracted from the JSON Web Token. Your microservices can always assume the authentication part is done already and trust this user Id. If you want to implement authorization, you may base it on this Id or on token scopes (see below).

X-Token-Scopes

Token scopes extracted from the JSON web token. Comma separated (eg. read,write)

Your microservice may use these for authorization purposes (restrict certain actions, etc).

X-Client-Ip

Original user IP address.

Basic output mutation

You can do basic JSON output mutation using output property of an action. Eg.

[
    'service' => 'service1',
    'method' => 'GET',
    'path' => '/pages/{page}',
    'sequence' => 0,
    'output_key' => 'data'
];

Response from service1 will be included in the final output under data key.

output_key can be an array to allow further mutation:

[
    'service' => 'service1',
    'method' => 'GET',
    'path' => '/pages/{page}',
    'sequence' => 0,
    'output_key' => [
        'id' => 'service_id',
        'title' => 'service_title',
        '*' => 'service_more'
    ]
];

This will assign contents of id property to garbage_id, title to service_title and the rest of the content will be inside of service_more property of the output JSON.

Performance

Performance is one of the key indicators of an API gateway and that's why we chose Lumen – bootstrap only takes ~25ms on a basic machine.

See an example of an aggregate request. First let's do separate requests to underlying microservices:

$ time curl http://service1.local/devices/5
{"id":5,"network_id":2,...}
real    0m0.025s

$ time curl http://service1.local/networks/2
{"id":2,...}
real    0m0.025s

$ time curl http://service2.local/visits/2
[{"id":1,...},{...}]
real    0m0.041s

So that's 91ms of real OS time – including all the web-server-related overhead. Let's now make a single aggregate request to the API gateway which behind the scenes will make the same 3 requests:

$ time curl http://gateway.local/devices/5/details
{"data":{"device":{...},"network":{"settings":{...},"visits":[]}}}
real    0m0.056s

And it's just 56ms for all 3 requests! Second and third requests were executed in parallel (in async mode).

This is pretty decent, we think!

Examples

Example 1: Single, simple microservice

Let's say we have a very simple setup: API Gateway + one microservice behind it.

First, we need to let the gateway know about this microservice by adding it to GATEWAY_SERVICES environment variable.

{
	"service": []
}

Where service is the nickname we chose for our microservice. The array is empty because we will rely on default settings. Our service has a valid Swagger documentation endpoint running on api/doc URL.

Next, we provide global settings on GATEWAY_GLOBAL environment variable:

{
	"prefix": "/v1",
	"timeout": 3.0,
	"doc_point": "/api/doc",
	"domain": "supercompany.io"
}

This tells the gateway that services that don't have explicit URLs provided, will be communicated at {serviceId}.{domain}, therefore our service will be contacted at service.supercompany.io, request timeout will be 3 seconds, Swagger documentation will be loaded from /api/doc and all routes will be prefixed with "v1".

We could however specify service's hostname explicitly using "hostname" key in the GATEWAY_SERVICES array.

Now we can run php artisan gateway:parse to force Vrata to parse Swagger documentation provided by this service. All documented routes will be exposed in this API gateway.

If you use our Docker image, this command will be executed every time you start a container.

Now, if your service had a route GET http://service.supercompany.io/users, it will be available as GET http://api-gateway.supercompany.io/v1/users and all requests will be subject to JSON Web Token check and rate limiting.

Don't forget to set PRIVATE_KEY and PUBLIC_KEY environment variables, they are necessary for authentication to work.

Example 2: Multiple microservices with aggregate requests

This time we are going to add two services behind our API gateway - one with Swagger 1 documentation and another with Swagger 2 documentation. Vrata detects Swagger version automatically, so we don't have to specify this anywhere. Let's first define GATEWAY_SERVICES environment variable:

{
	"core": [],
	"service1": []
}

So we have two services - "core" and "service1", Vrata will assume that DNS hostnames will match these.

Let's define GATEWAY_GLOBAL variable now - this variable contains global settings of the API gateway:

{
	"prefix": "/v1",
	"timeout": 10.0,
	"doc_point": "/api/doc",
	"domain": "live.vrata.io"
}

All routes imported from Swagger will be prefixed with "/v1" because of the first setting. 10 seconds is the timeout we give our API gateway for internal requests to microservices behind it. "doc_point" is the URI of Swagger documentation, and "domain" is the DNS domain that will be added to every service name.

Therefore, when Vrata tries to load Swagger documentation for "core" service, it will hit http://core.live.vrata.io/api/doc URL. If you have unique Swagger URIs per microservice - you can define "doc_point" for every service individually.

Setting these two variables is enough to start working with Vrata - it will import all routes from "core" and "service1" and start proxying requests to them.

However, if we need something more sophisticated - eg. an aggregated request that involves multiple microservices at the same time, we need to define a third environment variable - GATEWAY_ROUTES.

Consider this example:

[{
	"aggregate": true,
	"method": "GET",
	"path": "/v1/connections/{id}",
	"actions": {
		"venue": {
			"service": "core",
			"method": "GET",
			"path": "venues/{id}",
			"sequence": 0,
			"critical": true,
			"output_key": "venue"
		},
		"connections": {
			"service": "service1",
			"method": "GET",
			"path": "connections/{venue%data.id}",
			"sequence": 1,
			"critical": false,
			"output_key": {
				"data": "venue.clients"
			}
		},
		"access-lists": {
			"service": "service1",
			"method": "GET",
			"path": "/metadata/{venue%data.id}",
			"sequence": 1,
			"critical": false,
			"output_key": {
				"data": "venue.metadata"
			}
		}
	}
}, {
	"method": "GET",
	"path": "/v1/about",
	"public": true,
	"actions": [{
		"service": "service1",
		"method": "GET",
		"path": "static/about",
		"sequence": 0,
		"critical": true
	}]
}, {
	"method": "GET",
	"path": "/v1/history",
	"raw": true,
	"actions": [{
		"method": "GET",
		"service": "core",
		"path": "/connections/history"
	}]
}]

The config above defines 3 routes - two regular requests with custom settings and one aggregate request. Let's start with simple requests:

{
	"method": "GET",
	"path": "/v1/about",
	"public": true,
	"actions": [{
		"service": "service1",
		"method": "GET",
		"path": "static/about",
		"sequence": 0,
		"critical": true
	}]
}

This definition will add a "/v1/about" route to the API gateway that will be public - it won't require any access token at all, authentication will be bypassed. It will proxy request to http://service1.live.vrata.io/static/about and pass back whatever was returned.

Another simple route:

{
	"method": "GET",
	"path": "/v1/history",
	"raw": true,
	"actions": [{
		"method": "GET",
		"service": "core",
		"path": "/connections/history"
	}]
}

This will add a "/v1/history" endpoint that will request data from http://core.live.vrata.io/connections/history. Notice the "raw" flag - this means Vrata won't do any JSON parsing at all (and therefore you won't be able to mutate output as result). This is important for performance - PHP may choke if you json_decode() and then json_encode() a huge string

  • arrays and objects are very memory expensive in PHP.

And finally our aggregate route:

{
	"aggregate": true,
	"method": "GET",
	"path": "/v1/connections/{id}",
	"actions": {
		"venue": {
			"service": "core",
			"method": "GET",
			"path": "venues/{id}",
			"sequence": 0,
			"critical": true,
			"output_key": "venue"
		},
		"connections": {
			"service": "service1",
			"method": "GET",
			"path": "connections/{venue%data.id}",
			"sequence": 1,
			"critical": false,
			"output_key": {
				"data": "venue.clients"
			}
		},
		"access-lists": {
			"service": "service1",
			"method": "GET",
			"path": "/metadata/{venue%data.id}",
			"sequence": 1,
			"critical": false,
			"output_key": {
				"data": "venue.metadata"
			}
		}
	}
}

First property marks it as an aggregate route - that's self explanatory. The route will be mounted as "/v1/connections/{id}" where "id" will be any string or number. Then, this route involves 3 requests to microservices and two of them can be made in parallel - because they have the same sequence number of 1.

Vrata will first make a request to http://core.live.vrata.io/venues/{id} where {id} is the parameter from request. This route action is marked as critical - therefore, if it fails the whole request is abandoned. All output from this action will be presented in the final JSON output as "venue" property.

Then, two requests will be launched simultaneously - to http://service1.live.vrata.io/connections/{id} and another to http://service1.live.vrata.io/metadata/{id}. This time, {id} is taken from the output of the previous action. Vrata will collect all outputs from all requests and make them available to all following requests.

Since these two requests always happen later than the first one (because of the sequence setting), they can have access to its output. Notice {venue%data.id} in the paths - this refers to "venue" (name of the previous action) and "id" property of "data" object ("data.id" in dot notation).

Both actions are set to non-critical - if they fail, user will still receive a response, but corresponding fields will be empty.

We only take "data" JSON property from both responses and we inject it to the final response as "venue.clients" and "venue.metadata".

Example 3: Multiple microservices with aggregate POST / PUT / DELETE requests

Initial body of your POST, PUT or DELETE request come with origin tag usable in your json. You can use in your actions an optionnal body parameters for each requests. You can use origin tag to use the body sent in your initial request. You can also use the response of each actions in the body param like in a GET aggregate request.

{
	"aggregate": true,
	"method": "PUT",
	"path": "/v1/unregister/sendaccess",
	"actions": {	
	  "contact": {
		"service": "contact",
		"method": "PUT",
		"path": "unregister/newsletter",
		"sequence": 0,
		"critical": true,
		"body": {
			"email": "{origin%email}"
		},
		"output_key": "register"
	  },
	  "template": {
		"service": "notice",
		"method": "POST",
		"path": "notice/email/generate",
		"sequence": 1,
		"critical": true,
		"body": {
			"validationToken": "{contact%validationToken}",
			"noticeTypeId": "{contact%validationType}"
		},
		"output_key": "notice"
	  },
	  "check": {
		"service": "email",
		"method": "POST",
		"path": "email/send",
		"sequence": 2,
		"critical": true,
		"body": {
			"to": "{origin%email}",
			"sujet": "Email object",
			"queue_name": "urgent",
			"message_html": "{template%htmlTemplate}",
			"message_text": "text version",
			"from": "[email protected]",
			"nom": "Sender name"
		},
		"output_key": "result"
	  }
	}
}

License

The MIT License (MIT)

Copyright (c) 2017-2018 PoweredLocal

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

vrata's People

Contributors

alexshelkov avatar andrewgodman avatar dusterio avatar felipemfp avatar lijiebin avatar tpin85 avatar witschko avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

vrata's Issues

Alteração ParseServices para OpenId V3

Olá!!!
Primeiro parabéns pelo recurso disponibilizado. Espetacular.

Sugiro a inclusão da opção do OpenID para o command: ParseServices:

if ($data['openapi'] && preg_match('/^3./', $data['openapi']) && isset($data['paths']))
return $this->injectSettings($this->parseSwaggerTwo($data), $url, $docRoot, $serviceId);

image

Authentication to the microservices

Could I ask about authentication to the microservices?
Am I right in thinking that this setup could only be used 'as is' to consume microservices that you control/own due to there being no authentication between the gateway and the microservices?

Would you put a microservice between the API gateway and a third party service, just to handle the authentication and regulate the API of the third party service?

I really like this approach and your Medium article was a great read.

Get Image from microservices

First thanks for all !
I have i problem to get a image from the microservice because all the result is on JSON, How I can get the image by the gatway,

Regards

How to configure it for multitanent architecture?

Hi,
First of all thanks for making this kind of stuff for us, there are no other php support for API gateway. Its really helpful. But I do have one concern. I want to add multi tenancy support in my project along with this API gateway, so each customer shares the software application and also shares a individual database.

so please help me to run multiple websites using the same Laravel installation while keeping tenant specific data separated for fully independent multi-domain setups.

Thanks,
Anil

Want to contribute

I want to contribute on this API GATEWAY, I need if possible if you can help me start thank you.

Permission management

How do i do the permission management on vrata?
I have an API, using lumen by the way, thats have a complexe auth system, in there i can filter witch controler my user has access, but i want to transform that into a microservice, how i going to do that on vrata? If my auth stays on the vrata how my endpoint is going to know who is requesting? and how my endpoint its goind to know the user information? I don't want to duplicate code here, and i want to add later another api made of C++ to interact with. I don't know if i was clear enough.

Composer Dependancies.

Fresh install using composer has the following dependancy problems.

Failed to download codeclimate/php-test-reporter from source: Failed to clone https://github.com/codeclimate/php-test-reporter.git, git was not found, check that it is installed and in your PATH env.

sh: git: command not found

Now trying to download from dist

Package guzzle/guzzle is abandoned, you should avoid using it. Use guzzlehttp/guzzle instead.
Package satooshi/php-coveralls is abandoned, you should avoid using it. Use php-coveralls/php-coveralls instead.

Схема данных конфига

Где можно посмотреть полную схему данных конфигурации services, global и routes?
Столкнулся что не до конца понимаю что от меня требуется.
Пример: в config/gateway.php вроде все описано, но в описании репозитория вы говорите о том что в services можно указывать hostname.
Есть ли возможность для каждого сервиса задавать префикс для роутинга, например для сервиса service1 url будет service1/someMethod?

auth middlware not working

I dont set the public key in routes.json and middlware automatic set to auth, but this middlware not working and my service route not protected by auth middleware!
please help me!

App\Http\Request leads to conflict when dispatching internal routes

Hi there

I'm using plenty of your vrata-gateway-code in my own api-gateway and your code helped me very much on my way. But now I figured out a problem when using laravel passport with a proxy request. This means, I use an additional Controller (LoginController) that accepts post-params username and password and then does an internal request to Passport oauth/token to get the token - like it is shown in this article (sorry - German):
https://medium.com/@albrecht.mauersberger/spa-mit-vue-js-vuetify-laravel-lumen-und-passport-ii-83f7491297a6

But to reduce it - here the code of LoginControllers login function


public function login(Request $request)
    {
        $this->validate($request, [
            'username' => 'required',
            'password' => 'required',
        ]);

        $tokenRequest = Request::create(
            env('APP_URL') . 'api/oauth/token',
            'POST'
        );

        $tokenRequest->merge([
            'username' => $request->username,
            'password' => $request->password,
            'grant_type' => 'password',
            'client_id' => $this->client->id,
            'client_secret' => $this->client->secret,
            'scope' => '*'
        ]);

        return app()->dispatch($tokenRequest);
    }

there you see that it is dispatched an internal request to passport. And there the problem starts with the App\Http\Request-Class -> the dispatcher uses make('request') internally and now gets a App\Http\Request-Class what doesn't fit to this interal request and returns the originally that came from outside... - in short: my internal passport-request doesn't work any more... It took me several hours of debugging to find out, why my request didn't work - so maybe this helps somebody other...

I finally found a solution and I'd even suggest to include it to your project even if there is no internal request used... this solution totally removes the App\Http\Request-Class from your project. (I didn't fork, because I don't use your complete project... so I just share my solution here)

First change in Middleware: instead of attaching the Route with the function attachRoute we can use attributes of the original Request-Class - here my new middleware:

<?php

namespace App\Http\Middleware;

use App\Routing\RouteRegistry;
use Closure;
use Illuminate\Http\Request;

class HelperMiddleware
{
    /**
     * Handle an incoming request.
     *
     * @param Request $request
     * @param  \Closure  $next
     * @param string $id
     * @return mixed
     */
    public function handle(Request $request, Closure $next, $id)
    {
        $request->attributes->add([
            'route' => app()->make(RouteRegistry::class)->getRoute($id)
        ]);

        return $next($request);
    }
}

now the route-object is added to the Illuminate Requests attributes.

Next changes in GatewayController
also replace App\Http\Request with Illuminate\Http\Request
and then use this:
$request->attributes->get('route')
instead of
$request->getRoute()

To receive all route-params you don't need an own Route-Resolver - it can be done with the standard-Request-Class:
$request->route()[2]
this always returns the params in Lumen (route() function always returns the route-array). so I replaced all calls of
$request->getRouteParams() with $request->route()[2]

So now all functions except "route()" of the App\Http\Request-Class aren't used any more...
and thats now the reason why I don't open a Merge-Request, because in MY application it seems like this functionality is also not necessary - so I just removed it, and the route()-Function of the base-class works for me... But it might be, that this doesn't work in your whole application - I'm not quite sure...

The additional benefit: I could remove the whole part of binding the own request-class in AppServiceProvider, no own RouteResolver, no own prepareRequest-Call, all the base-functionallity runs smooth. I currently use no trustedproxys - but to get this running again, I'd include package fideloper/proxy

I gues this solution could also work for you and increase performance additionally.
I'm looking forward for comments

Any plan to upgrade for lumen 6.x?

Hi there, I've been trying to migrate a full monolithic app to microservices, and so far Vrata has been the best option that I could find, but I'm not sure if it is still been supported, latest requirement is lumen 5.3, or do lumen version wouldn't matter?

So, is it a future proof choice to go with Vrata?

Thank you.

Example with a simple microservice

Hi I was looking to the implementation but still don't know how to interact with a service.
It is possible to see an example with a simple service?
Also a license would be awesome, thanks

How authenticate requests to microservices?

Hi, Thank you very much for this great api gateway! But you did't say anything about authenticating between gateway and microservices !
For example we have two microservice : service1 and service2 + vrata as api gateway.

I have three problems now:

1.Now we want to send request from service1 to service2 by vrata. In which one we should install lumen-passport? in vrata ? in two microservices? or all three?

2.How to determine in the vrata that a route needs permission ? If we just do not use 'public' => true, is it enough?

3.Also if access to service1 requires authentication, how to do it?

Thanks

Upgrade to Lumen 5.6

Please upgrade your projects Lumen package and other packages to latest version

How use this gate to register user?

I searching this code and dont see register routes. When i use routes */oauth/token and send grant_type='password', client_id, client_secret i must send username and password too. When i find it? When i using grant_type='client_credentials' i get token without username and password but when i try send request GET on /me i get Unauthorized error.

Tutorial video

First of all thanks for this good lib. But a youtube (or any) tutorial video would be nice to understand the whole flow.

Cheers.

Guzzle Dependency

Hi!

A friend sent me a link to your libraries.io description and I'm excited to get it running. I noticed as I install that the composer dependency is behind using guzzle/guzzle instead of guzzlehttp/guzzle.

Are you interested in a PR to update this? I'd be happy to contribute.

Custom header forwarding

Hi!

I was just wondering if it is somehow possible to forward custom headers that come with the original request to the final microservice?

Best,
Philipp

Cant't get post data when request a service by `POST` method

Because the data of setBody not in $_POST but in php://input

 private function simpleRequest(Request $request, RestClient $client)
    {
        if ($request->getRoute()->isAggregate()) throw new NotImplementedException('Aggregate ' . strtoupper($request->method()) . 's are not implemented yet');

        $client->setBody($request->getContent());

        if (count($request->allFiles()) !== 0) {
            $client->setFiles($request->allFiles());
        }

        $parametersJar = array_merge($request->getRouteParams(), ['query_string' => $request->getQueryString()]);
        $response = $client->syncRequest($this->actions->first()->first(), $parametersJar);

        return $this->presenter->format((string)$response->getBody(), $response->getStatusCode());
    }

Cant run php artisan due to missing views config

Maybe I'm over stretching this, but I'm trying to run the php artisan command from a fresh vrata instalation usgin the composer create-project, and it keeps saying the message

In ServiceProvider.php line 97:                                                      
  Trying to access array offset on value of type null

I've narrowed dwn to two classes that call the method "loadViewsFrom" which is the one that fails to find the views config file in the config directory, and those two classes are "PassportServiceProvider", "PaginationServiceProvider".

So as I mentioned above, maybe I'm trying to do somthing that is totally unnecesary like running the "php artisan" command to work with vrata, but I'm trying to wrap my head arround on how vrata do its things, I understand that there are no views needed in vrata, but lets say how does vrata install passport correctly if it cant run the php artisan command.

I've noticed that it runs migrations from the ci/start.sh when using docker (which I haven't done, I'm also figuring out how to pass the json to the docker env correctly), but if I want to do it myself from fresh instalation using composer create-project, I cant run passport:install nor gateway:parse.

Now, I ended commenting the calls to the "loadViewsFrom" from those 2 providers and I was able to run "php artisan", I know it might not be an issue using the docker method, but do I have to do that every time I install a vrata project composer way?

Also, any clarification on why maybe it isn't a problem at all would be appreciated. Thank you.

Support PostgreSQL driver

Hi!

I just recognized (after some hours) that there is no PostgreSQL driver shipped with the Docker image. Since we use PostgreSQL as our user database and Lumen supports it from scratch it would be nice if the driver would come pre-installed with the Docker image.

Best,
Philipp

No .env.example file in project

Installing poweredlocal/vrata (0.2.0)

  • Installing poweredlocal/vrata (0.2.0): Loading from cache
    Created project in vrata/

php -r "copy('.env.example', '.env');"
PHP Warning: copy(.env.example): failed to open stream: No such file or directory in Command line code on line 1
PHP Stack trace:
PHP 1. {main}() Command line code:0
PHP 2. copy() Command line code:1

Docker image should have tag

As title, it's good to see that this repository has the Docker image and it's available on Docker hub page.

I think we need to tag the version and it can let developers know which versions are stable.

And nobody want to use the unstable version to build Docker container on the production.

Question about micro-services Authentication

Hi ! @dusterio 👋
First thanks for all !

I created this issue about micro-services authentication questions i have.
Why not pass JWT to micro-services and every micro-service check JWT token validity with Public KEY ?

And i would like to know what is the best practice for you, if the gateway send JWT token to micro-services, it's better to send in X-Access-Token header or directly in Authorization ?

This question is not clearly defined in other forums.

Thanks,
Léo

composer install error

when i wrire composer install command, i get this error
[Composer\Json\JsonValidationException]
"./composer.json" does not match the expected JSON schema:

REQUEST

Hello can i request for sample postman collection? Thanks!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.