Merge branch 'master' into 'main'

Master

See merge request izyim/prototypes/lumen-microservices/microservice-api-gateway!1
This commit is contained in:
EDMOND MING
2022-09-30 11:24:46 +00:00
46 changed files with 1388 additions and 0 deletions
+25
View File
@@ -0,0 +1,25 @@
APP_NAME=ApiGateway
APP_ENV=local
APP_KEY=
APP_DEBUG=true
APP_URL=http://localhost
APP_TIMEZONE=UTC
LOG_CHANNEL=stack
LOG_SLACK_WEBHOOK_URL=
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=lu-ms1-api_gateway
DB_USERNAME=
DB_PASSWORD=
CACHE_DRIVER=file
QUEUE_CONNECTION=sync
PRODUCTS_SERVICE_BASE_URI=http://localhost:8100/api
PRODUCTS_SERVICE_SECRET=
ORDERS_SERVICE_BASE_URI=http://localhost:8200/api
ORDERS_SERVICE_SECRET=
+8
View File
@@ -0,0 +1,8 @@
/vendor
/.idea
Homestead.json
Homestead.yaml
.env
storage/*.key
composer.lock
+8
View File
@@ -0,0 +1,8 @@
/vendor
/.idea
Homestead.json
Homestead.yaml
.env
storage/*.key
composer.lock
View File
+29
View File
@@ -0,0 +1,29 @@
<?php
declare(strict_types = 1);
namespace App\Console;
use Illuminate\Console\Scheduling\Schedule;
use Laravel\Lumen\Console\Kernel as ConsoleKernel;
class Kernel extends ConsoleKernel
{
/**
* The Artisan commands provided by your application.
*
* @var array
*/
protected $commands = [];
/**
* Define the application's command schedule.
*
* @param \Illuminate\Console\Scheduling\Schedule $schedule
*
* @return void
*/
protected function schedule(Schedule $schedule)
{
}
}
+12
View File
@@ -0,0 +1,12 @@
<?php
declare(strict_types = 1);
namespace App\Events;
use Illuminate\Queue\SerializesModels;
abstract class Event
{
use SerializesModels;
}
+15
View File
@@ -0,0 +1,15 @@
<?php
declare(strict_types = 1);
namespace App\Events;
class ExampleEvent extends Event
{
/**
* Create a new event instance.
*/
public function __construct()
{
}
}
+106
View File
@@ -0,0 +1,106 @@
<?php
declare(strict_types = 1);
namespace App\Exceptions;
use App\Traits\ApiResponse;
use Exception;
use GuzzleHttp\Exception\ClientException;
use Illuminate\Auth\AuthenticationException;
use Illuminate\Http\Response;
use Illuminate\Validation\ValidationException;
use Illuminate\Auth\Access\AuthorizationException;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Laravel\Lumen\Exceptions\Handler as ExceptionHandler;
use Symfony\Component\HttpKernel\Exception\HttpException;
use function env;
class Handler extends ExceptionHandler
{
use ApiResponse;
/**
* A list of the exception types that should not be reported.
*
* @var array
*/
protected $dontReport = [
AuthorizationException::class,
HttpException::class,
ModelNotFoundException::class,
ValidationException::class,
];
/**
* Report or log an exception.
*
* This is a great spot to send exceptions to Sentry, Bugsnag, etc.
*
* @param \Exception $exception
* @return void
*/
public function report(Exception $exception)
{
parent::report($exception);
}
/**
* Render an exception into an HTTP response.
*
* @param \Illuminate\Http\Request $request
* @param \Exception $exception
* @return \Illuminate\Http\Response
*/
public function render($request, Exception $exception)
{
if ($exception instanceof HttpException) {
$errorCode = $exception->getStatusCode();
$errorMessage = Response::$statusTexts[$errorCode];
return $this->errorResponse($errorMessage, $errorCode);
}
if ($exception instanceof ModelNotFoundException) {
$model = strtolower(class_basename($exception->getModel()));
return $this->errorResponse(
"Does not exist any instance of {$model} with a given id",
Response::HTTP_NOT_FOUND);
}
if ($exception instanceof AuthorizationException) {
return $this->errorResponse(
$exception->getMessage(),
Response::HTTP_FORBIDDEN);
}
if ($exception instanceof AuthenticationException) {
return $this->errorResponse(
$exception->getMessage(),
Response::HTTP_UNAUTHORIZED);
}
if ($exception instanceof ValidationException) {
$errors = $exception->validator->errors()->getMessages();
return $this->errorResponse(
$errors,
Response::HTTP_UNPROCESSABLE_ENTITY);
}
if ($exception instanceof ClientException) {
$errorMessage = $exception->getResponse()->getBody();
$errorCode = $exception->getCode();
return $this->errorMessage($errorMessage, $errorCode);
}
if (env('APP_DEBUG', false)) {
return parent::render($request, $exception);
}
return $this->errorResponse(
"Unexpected error. Try later!",
Response::HTTP_INTERNAL_SERVER_ERROR);
}
}
+13
View File
@@ -0,0 +1,13 @@
<?php
declare(strict_types = 1);
namespace App\Http\Controllers;
use App\Traits\ApiResponse;
use Laravel\Lumen\Routing\Controller as BaseController;
class Controller extends BaseController
{
use ApiResponse;
}
+83
View File
@@ -0,0 +1,83 @@
<?php
declare(strict_types = 1);
namespace App\Http\Controllers;
use App\Services\OrderService;
use App\Services\ProductService;
use Illuminate\Http\Request;
class OrderController extends Controller
{
/**
* @var \App\Services\OrderService
*/
protected $orderService;
/**
* @var \App\Services\ProductService
*/
protected $productService;
/**
* OrderController constructor.
*
* @param \App\Services\OrderService $orderService
* @param \App\Services\ProductService $productService
*/
public function __construct(OrderService $orderService, ProductService $productService)
{
$this->orderService = $orderService;
$this->productService = $productService;
}
/**
* @return mixed
*/
public function index()
{
return $this->successResponse($this->orderService->fetchOrders());
}
/**
* @param $order
*
* @return mixed
*/
public function show($order)
{
return $this->successResponse($this->orderService->fetchOrder($order));
}
/**
* @param \Illuminate\Http\Request $request
*
* @return mixed
*/
public function store(Request $request)
{
return $this->successResponse($this->orderService->createOrder($request->all()));
}
/**
* @param \Illuminate\Http\Request $request
* @param $order
*
* @return mixed
*/
public function update(Request $request, $order)
{
return $this->successResponse($this->orderService->updateOrder($order, $request->all()));
}
/**
* @param $order
*
* @return mixed
*/
public function destroy($order)
{
return $this->successResponse($this->orderService->deleteOrder($order));
}
}
@@ -0,0 +1,73 @@
<?php
declare(strict_types = 1);
namespace App\Http\Controllers;
use App\Services\ProductService;
use Illuminate\Http\Request;
class ProductController extends Controller
{
private $productService;
/**
* ProductController constructor.
*
* @param \App\Services\ProductService $productService
*/
public function __construct(ProductService $productService)
{
$this->productService = $productService;
}
/**
* @return mixed
*/
public function index()
{
return $this->successResponse($this->productService->fetchProducts());
}
/**
* @param $product
*
* @return mixed
*/
public function show($product)
{
return $this->successResponse($this->productService->fetchProduct($product));
}
/**
* @param \Illuminate\Http\Request $request
*
* @return mixed
*/
public function store(Request $request)
{
return $this->successResponse($this->productService->createProduct($request->all()));
}
/**
* @param \Illuminate\Http\Request $request
* @param $product
*
* @return mixed
*/
public function update(Request $request, $product)
{
return $this->successResponse($this->productService->updateProduct($product, $request->all()));
}
/**
* @param $product
*
* @return mixed
*/
public function destroy($product)
{
return $this->successResponse($this->productService->deleteProduct($product));
}
}
+48
View File
@@ -0,0 +1,48 @@
<?php
declare(strict_types = 1);
namespace App\Http\Middleware;
use Closure;
use Illuminate\Contracts\Auth\Factory as Auth;
use function response;
class Authenticate
{
/**
* The authentication guard factory instance.
*
* @var \Illuminate\Contracts\Auth\Factory
*/
protected $auth;
/**
* Create a new middleware instance.
*
* @param \Illuminate\Contracts\Auth\Factory $auth
* @return void
*/
public function __construct(Auth $auth)
{
$this->auth = $auth;
}
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @param string|null $guard
* @return mixed
*/
public function handle($request, Closure $next, $guard = null)
{
if ($this->auth->guard($guard)->guest()) {
return response('Unauthorized.', 401);
}
return $next($request);
}
}
+22
View File
@@ -0,0 +1,22 @@
<?php
declare(strict_types = 1);
namespace App\Http\Middleware;
use Closure;
class ExampleMiddleware
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
return $next($request);
}
}
+26
View File
@@ -0,0 +1,26 @@
<?php
declare(strict_types = 1);
namespace App\Jobs;
class ExampleJob extends Job
{
/**
* Create a new job instance.
*
* @return void
*/
public function __construct()
{
}
/**
* Execute the job.
*
* @return void
*/
public function handle() : void
{
}
}
+26
View File
@@ -0,0 +1,26 @@
<?php
declare(strict_types = 1);
namespace App\Jobs;
use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
abstract class Job implements ShouldQueue
{
/*
|--------------------------------------------------------------------------
| Queueable Jobs
|--------------------------------------------------------------------------
|
| This job base class provides a central location to place any logic that
| is shared across all of your jobs. The trait included with the class
| provides access to the "queueOn" and "delay" queue helper methods.
|
*/
use InteractsWithQueue, Queueable, SerializesModels;
}
+29
View File
@@ -0,0 +1,29 @@
<?php
declare(strict_types = 1);
namespace App\Listeners;
use App\Events\ExampleEvent;
class ExampleListener
{
/**
* Create the event listener.
*
* @return void
*/
public function __construct()
{
}
/**
* Handle the event.
*
* @param ExampleEvent $event
* @return void
*/
public function handle(ExampleEvent $event)
{
}
}
+19
View File
@@ -0,0 +1,19 @@
<?php
declare(strict_types = 1);
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*
* @return void
*/
public function register()
{
}
}
+41
View File
@@ -0,0 +1,41 @@
<?php
declare(strict_types = 1);
namespace App\Providers;
use Dusterio\LumenPassport\LumenPassport;
use Illuminate\Support\ServiceProvider;
class AuthServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*
* @return void
*/
public function register()
{
}
/**
* Boot the authentication services for the application.
* If you desire to handle the request via simple mechanism
* $this->app['auth']->viaRequest('api', function ($request) {
* if ($request->input('api_token')) {
* return User::where('api_token', $request->input('api_token'))->first();
* }
* });
*
* @return void
*/
public function boot()
{
// Here you may define how you wish users to be authenticated for your Lumen
// application. The callback which receives the incoming request instance
// should return either a User instance or null. You're free to obtain
// the User instance via an API token or any other method necessary.
LumenPassport::routes($this->app->router);
}
}
+21
View File
@@ -0,0 +1,21 @@
<?php
declare(strict_types = 1);
namespace App\Providers;
use Laravel\Lumen\Providers\EventServiceProvider as ServiceProvider;
class EventServiceProvider extends ServiceProvider
{
/**
* The event listener mappings for the application.
*
* @var array
*/
protected $listen = [
'App\Events\ExampleEvent' => [
'App\Listeners\ExampleListener',
],
];
}
+79
View File
@@ -0,0 +1,79 @@
<?php
declare(strict_types = 1);
namespace App\Services;
use App\Traits\RequestService;
use function config;
class OrderService
{
use RequestService;
/**
* @var string
*/
protected $baseUri;
/**
* @var string
*/
protected $secret;
public function __construct()
{
$this->baseUri = config('services.orders.base_uri');
$this->secret = config('services.orders.secret');
}
/**
* @return string
*/
public function fetchOrders() : string
{
return $this->request('GET', '/api/order');
}
/**
* @param $order
*
* @return string
*/
public function fetchOrder($order) : string
{
return $this->request('GET', "/api/order/{$order}");
}
/**
* @param $data
*
* @return string
*/
public function createOrder($data) : string
{
return $this->request('POST', '/api/order', $data);
}
/**
* @param $order
* @param $data
*
* @return string
*/
public function updateOrder($order, $data) : string
{
return $this->request('PATCH', "/api/order/{$order}", $data);
}
/**
* @param $order
*
* @return string
*/
public function deleteOrder($order) : string
{
return $this->request('DELETE', "/api/order/{$order}");
}
}
+82
View File
@@ -0,0 +1,82 @@
<?php
declare(strict_types = 1);
namespace App\Services;
use App\Traits\RequestService;
use function config;
class ProductService
{
use RequestService;
/**
* @var string
*/
protected $baseUri;
/**
* @var string
*/
protected $secret;
/**
* ProductService constructor.
*/
public function __construct()
{
$this->baseUri = config('services.products.base_uri');
$this->secret = config('services.products.secret');
}
/**
* @return string
*/
public function fetchProducts() : string
{
return $this->request('GET', '/api/product');
}
/**
* @param $product
*
* @return string
*/
public function fetchProduct($product) : string
{
return $this->request('GET', "/api/product/{$product}");
}
/**
* @param $data
*
* @return string
*/
public function createProduct($data) : string
{
return $this->request('POST', '/api/product', $data);
}
/**
* @param $product
* @param $data
*
* @return string
*/
public function updateProduct($product, $data) : string
{
return $this->request('PATCH', "/api/product/{$product}", $data);
}
/**
* @param $product
*
* @return string
*/
public function deleteProduct($product) : string
{
return $this->request('DELETE', "/api/product/{$product}");
}
}
+45
View File
@@ -0,0 +1,45 @@
<?php
declare(strict_types = 1);
namespace App\Traits;
use Illuminate\Http\Response;
use function response;
trait ApiResponse
{
/**
* @param $data
* @param int $statusCode
*
* @return mixed
*/
public function successResponse($data, $statusCode = Response::HTTP_OK)
{
return response($data, $statusCode)->header('Content-Type', 'application/json');
}
/**
* @param $errorMessage
* @param $statusCode
*
* @return mixed
*/
public function errorResponse($errorMessage, $statusCode)
{
return response()->json(['error' => $errorMessage, 'error_code' => $statusCode], $statusCode);
}
/**
* @param $errorMessage
* @param $statusCode
*
* @return mixed
*/
public function errorMessage($errorMessage, $statusCode)
{
return response($errorMessage, $statusCode)->header('Content-Type', 'application/json');
}
}
+39
View File
@@ -0,0 +1,39 @@
<?php
declare(strict_types = 1);
namespace App\Traits;
use GuzzleHttp\Client;
trait RequestService
{
/**
* @param $method
* @param $requestUrl
* @param array $formParams
* @param array $headers
*
* @return string
* @throws \GuzzleHttp\Exception\GuzzleException
*/
public function request($method, $requestUrl, $formParams = [], $headers = []) : string
{
$client = new Client([
'base_uri' => $this->baseUri
]);
if (isset($this->secret)) {
$headers['Authorization'] = $this->secret;
}
$response = $client->request($method, $requestUrl,
[
'form_params' => $formParams,
'headers' => $headers
]
);
return $response->getBody()->getContents();
}
}
+34
View File
@@ -0,0 +1,34 @@
<?php
declare(strict_types = 1);
namespace App;
use Illuminate\Auth\Authenticatable;
use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract;
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
use Illuminate\Database\Eloquent\Model;
use Laravel\Lumen\Auth\Authorizable;
class User extends Model implements AuthenticatableContract, AuthorizableContract
{
use Authenticatable, Authorizable;
/**
* The attributes that are mass assignable.
*
* @var string[]
*/
protected $fillable = [
'name', 'email'
];
/**
* The attributes excluded from the model's JSON form.
*
* @var array
*/
protected $hidden = [
'password',
];
}
+35
View File
@@ -0,0 +1,35 @@
#!/usr/bin/env php
<?php
use Symfony\Component\Console\Input\ArgvInput;
use Symfony\Component\Console\Output\ConsoleOutput;
/*
|--------------------------------------------------------------------------
| Create The Application
|--------------------------------------------------------------------------
|
| First we need to get an application instance. This creates an instance
| of the application / container and bootstraps the application so it
| is ready to receive HTTP / Console requests from the environment.
|
*/
$app = require __DIR__.'/bootstrap/app.php';
/*
|--------------------------------------------------------------------------
| Run The Artisan Application
|--------------------------------------------------------------------------
|
| When we run the console application, the current CLI command will be
| executed in this console and the response sent back to a terminal
| or another output device for the developers. Here goes nothing!
|
*/
$kernel = $app->make(
'Illuminate\Contracts\Console\Kernel'
);
exit($kernel->handle(new ArgvInput, new ConsoleOutput));
+118
View File
@@ -0,0 +1,118 @@
<?php
declare(strict_types = 1);
require_once __DIR__.'/../vendor/autoload.php';
try {
(new Laravel\Lumen\Bootstrap\LoadEnvironmentVariables(
dirname(__DIR__)
))->bootstrap();
} catch (Dotenv\Exception\InvalidPathException $e) {
//
}
/*
|--------------------------------------------------------------------------
| Create The Application
|--------------------------------------------------------------------------
|
| Here we will load the environment and create the application instance
| that serves as the central piece of this framework. We'll use this
| application as an "IoC" container and router for this framework.
|
*/
$app = new Laravel\Lumen\Application(
dirname(__DIR__)
);
$app->withFacades();
$app->withEloquent();
$app->configure('services');
$app->configure('auth');
/*
|--------------------------------------------------------------------------
| Register Container Bindings
|--------------------------------------------------------------------------
|
| Now we will register a few bindings in the service container. We will
| register the exception handler and the console kernel. You may add
| your own bindings here if you like or you can make another file.
|
*/
$app->singleton(
Illuminate\Contracts\Debug\ExceptionHandler::class,
App\Exceptions\Handler::class
);
$app->singleton(
Illuminate\Contracts\Console\Kernel::class,
App\Console\Kernel::class
);
/*
|--------------------------------------------------------------------------
| Register Middleware
|--------------------------------------------------------------------------
|
| Next, we will register the middleware with the application. These can
| be global middleware that run before and after each request into a
| route or middleware that'll be assigned to some specific routes.
|
*/
// $app->middleware([
// App\Http\Middleware\ExampleMiddleware::class
// ]);
$app->routeMiddleware([
'auth' => App\Http\Middleware\Authenticate::class,
'client.credentials' => \Laravel\Passport\Http\Middleware\CheckClientCredentials::class,
]);
/*
|--------------------------------------------------------------------------
| Register Service Providers
|--------------------------------------------------------------------------
|
| Here we will register all of the application's service providers which
| are used to bind services into the container. Service providers are
| totally optional, so you are not required to uncomment this line.
|
*/
// $app->register(App\Providers\AppServiceProvider::class);
$app->register(App\Providers\AuthServiceProvider::class);
// $app->register(App\Providers\EventServiceProvider::class);
$app->register(Laravel\Passport\PassportServiceProvider::class);
$app->register(Dusterio\LumenPassport\PassportServiceProvider::class);
/*
|--------------------------------------------------------------------------
| Load The Application Routes
|--------------------------------------------------------------------------
|
| Next we will include the routes file so that they can all be added to
| the application. This will provide all of the URLs the application
| can respond to, as well as the controllers that may handle them.
|
*/
$app->router->group([
'namespace' => 'App\Http\Controllers',
], function ($router) {
require __DIR__.'/../routes/web.php';
});
return $app;
+46
View File
@@ -0,0 +1,46 @@
{
"name": "laravel/lumen",
"description": "The Laravel Lumen Framework.",
"keywords": ["framework", "laravel", "lumen"],
"license": "MIT",
"type": "project",
"require": {
"php": ">=7.1.3",
"dusterio/lumen-passport": "^0.2.15",
"guzzlehttp/guzzle": "^6.5",
"laravel/lumen-framework": "5.8.*",
"lcobucci/jwt": "3.3.3",
"vlucas/phpdotenv": "^3.3"
},
"require-dev": {
"fzaninotto/faker": "~1.4",
"mockery/mockery": "~1.0",
"phpunit/phpunit": "~7.0"
},
"autoload": {
"classmap": [
"database/seeds",
"database/factories"
],
"psr-4": {
"App\\": "app/"
}
},
"autoload-dev": {
"classmap": [
"tests/"
]
},
"scripts": {
"post-root-package-install": [
"@php -r \"file_exists('.env') || copy('.env.example', '.env');\""
]
},
"config": {
"preferred-install": "dist",
"sort-packages": true,
"optimize-autoloader": true
},
"minimum-stability": "dev",
"prefer-stable": true
}
+24
View File
@@ -0,0 +1,24 @@
<?php
declare(strict_types = 1);
return [
'defaults' => [
'guard' => 'api',
'passwords' => 'users',
],
'guards' => [
'api' => [
'driver' => 'passport',
'provider' => 'users',
],
],
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => \App\User::class
]
]
];
+14
View File
@@ -0,0 +1,14 @@
<?php
declare(strict_types = 1);
return [
'products' => [
'base_uri' => env('PRODUCTS_SERVICE_BASE_URI'),
'secret' => env('PRODUCTS_SERVICE_SECRET')
],
'orders' => [
'base_uri' => env('ORDERS_SERVICE_BASE_URI'),
'secret' => env('ORDERS_SERVICE_SECRET'),
]
];
+14
View File
@@ -0,0 +1,14 @@
<?php
declare(strict_types = 1);
/*
|--------------------------------------------------------------------------
| Model Factories
|--------------------------------------------------------------------------
|
| Here you may define all of your model factories. Model factories give
| you a convenient way to create models for testing and seeding your
| database. Just tell the factory how a default model should look.
|
*/
View File
@@ -0,0 +1,36 @@
<?php
declare(strict_types = 1);
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class AddUsersTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up() : void
{
Schema::create('users', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('name', 256);
$table->string('email', 256);
$table->string('password', 512);
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down() : void
{
Schema::dropIfExists('users');
}
}
+19
View File
@@ -0,0 +1,19 @@
<?php
declare(strict_types = 1);
use Illuminate\Database\Seeder;
class DatabaseSeeder extends Seeder
{
/**
* Run the database seeds.
*
* @return void
*/
public function run()
{
\Illuminate\Support\Facades\Artisan::call('passport:install');
$this->call(UserTableSeeder::class);
}
}
+23
View File
@@ -0,0 +1,23 @@
<?php
declare(strict_types = 1);
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\Hash;
class UserTableSeeder extends Seeder
{
/**
* Run the database seeds.
*
* @return void
*/
public function run()
{
\App\User::create([
'name' => 'user1',
'email' => 'user1@gmail.com',
'password' => Hash::make('123456')
]);
}
}
+26
View File
@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit backupGlobals="false"
backupStaticAttributes="false"
bootstrap="bootstrap/app.php"
colors="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
stopOnFailure="false">
<testsuites>
<testsuite name="Application Test Suite">
<directory suffix="Test.php">./tests</directory>
</testsuite>
</testsuites>
<filter>
<whitelist processUncoveredFilesFromWhitelist="true">
<directory suffix=".php">./app</directory>
</whitelist>
</filter>
<php>
<env name="APP_ENV" value="testing"/>
<env name="CACHE_DRIVER" value="array"/>
<env name="QUEUE_CONNECTION" value="sync"/>
</php>
</phpunit>
+21
View File
@@ -0,0 +1,21 @@
<IfModule mod_rewrite.c>
<IfModule mod_negotiation.c>
Options -MultiViews -Indexes
</IfModule>
RewriteEngine On
# Handle Authorization Header
RewriteCond %{HTTP:Authorization} .
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
# Redirect Trailing Slashes If Not A Folder...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} (.+)/$
RewriteRule ^ %1 [L,R=301]
# Handle Front Controller...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
</IfModule>
+30
View File
@@ -0,0 +1,30 @@
<?php
declare(strict_types = 1);
/*
|--------------------------------------------------------------------------
| Create The Application
|--------------------------------------------------------------------------
|
| First we need to get an application instance. This creates an instance
| of the application / container and bootstraps the application so it
| is ready to receive HTTP / Console requests from the environment.
|
*/
$app = require __DIR__.'/../bootstrap/app.php';
/*
|--------------------------------------------------------------------------
| Run The Application
|--------------------------------------------------------------------------
|
| Once we have the application, we can handle the incoming request
| through the kernel, and send the associated response back to
| the client's browser allowing them to enjoy the creative
| and wonderful application we have prepared for them.
|
*/
$app->run();
+21
View File
@@ -0,0 +1,21 @@
# Lumen PHP Framework
[![Build Status](https://travis-ci.org/laravel/lumen-framework.svg)](https://travis-ci.org/laravel/lumen-framework)
[![Total Downloads](https://poser.pugx.org/laravel/lumen-framework/d/total.svg)](https://packagist.org/packages/laravel/lumen-framework)
[![Latest Stable Version](https://poser.pugx.org/laravel/lumen-framework/v/stable.svg)](https://packagist.org/packages/laravel/lumen-framework)
[![Latest Unstable Version](https://poser.pugx.org/laravel/lumen-framework/v/unstable.svg)](https://packagist.org/packages/laravel/lumen-framework)
[![License](https://poser.pugx.org/laravel/lumen-framework/license.svg)](https://packagist.org/packages/laravel/lumen-framework)
Laravel Lumen is a stunningly fast PHP micro-framework for building web applications with expressive, elegant syntax. We believe development must be an enjoyable, creative experience to be truly fulfilling. Lumen attempts to take the pain out of development by easing common tasks used in the majority of web projects, such as routing, database abstraction, queueing, and caching.
## Official Documentation
Documentation for the framework can be found on the [Lumen website](https://lumen.laravel.com/docs).
## Security Vulnerabilities
If you discover a security vulnerability within Lumen, please send an e-mail to Taylor Otwell at taylor@laravel.com. All security vulnerabilities will be promptly addressed.
## License
The Lumen framework is open-sourced software licensed under the [MIT license](https://opensource.org/licenses/MIT).
View File
+35
View File
@@ -0,0 +1,35 @@
<?php
declare(strict_types = 1);
/*
|--------------------------------------------------------------------------
| Application Routes
|--------------------------------------------------------------------------
|
| Here is where you can register all of the routes for an application.
| It is a breeze. Simply tell Lumen the URIs it should respond to
| and give it the Closure to call when that URI is requested.
|
*/
// $router->group(['prefix' => 'api', 'middleware' => ['client.credentials']], function () use ($router) {
$router->group(['prefix' => 'api'], function () use ($router) {
$router->group(['prefix' => 'product'], function () use ($router) {
$router->get('/', ['uses' => 'ProductController@index']);
$router->post('/', ['uses' => 'ProductController@store']);
$router->get('/{product}', ['uses' => 'ProductController@show']);
$router->patch('/{product}', ['uses' => 'ProductController@update']);
$router->delete('/{product}', ['uses' => 'ProductController@destroy']);
});
$router->group(['prefix' => 'order'], function () use ($router) {
$router->get('/', ['uses' => 'OrderController@index']);
$router->post('/', ['uses' => 'OrderController@store']);
$router->get('/{order}', ['uses' => 'OrderController@show']);
$router->patch('/{order}', ['uses' => 'OrderController@update']);
$router->delete('/{order}', ['uses' => 'OrderController@destroy']);
});
});
+2
View File
@@ -0,0 +1,2 @@
*
!.gitignore
+2
View File
@@ -0,0 +1,2 @@
*
!.gitignore
+2
View File
@@ -0,0 +1,2 @@
*
!.gitignore
+2
View File
@@ -0,0 +1,2 @@
*
!.gitignore
+21
View File
@@ -0,0 +1,21 @@
<?php
use Laravel\Lumen\Testing\DatabaseMigrations;
use Laravel\Lumen\Testing\DatabaseTransactions;
class ExampleTest extends TestCase
{
/**
* A basic test example.
*
* @return void
*/
public function testExample()
{
$this->get('/');
$this->assertEquals(
$this->app->version(), $this->response->getContent()
);
}
}
+14
View File
@@ -0,0 +1,14 @@
<?php
abstract class TestCase extends Laravel\Lumen\Testing\TestCase
{
/**
* Creates the application.
*
* @return \Laravel\Lumen\Application
*/
public function createApplication()
{
return require __DIR__.'/../bootstrap/app.php';
}
}