Artisan commands with HTTP
There might be some times you wanted to execute an Artisan command, but you did not have access to shell or SSH. Here we brought REST API solution for you.
You are able to run Artisan commands by REST APIs easily.
'README.md need to be updated'
To use this package, you should install it alongside Laravel v9.21 and PHP v8.0 or higher.
you can install it via Composer package manager:
composer require aariow/artisan-api --dev
Although, Artisan-Api has production decetor itself, it is possible to install it globally.
As its name explains, all commands are available via HTTP with POST method. All commands will be generated as routes and integrated into Laravel Routing system. You only need to send a POST request and follow the signature, like other REST API endpoints.
There are two kinds of commands; one is normal commands like php artisan list
or php artisan cache:clear
, and the second form is GeneratorCommands
which tend to create files within your application like make:model
and make:migration
. These kind of commands have different purposes, you should follow diffenerent convention.
GeneratorCommand
are instance ofIlluminate\Console\GeneratorCommand
that extendsIlluminate\Console\Command
class.
All commands existed by default or created by you will be discovered automatically and you do not have to do anything manually. Thus, their endpoints will be generated dynamically to your application. So if you delete/add any command class, there is no reason to worry.
Let's dive into using endpoints:
Routes are generated with the following format:
https://domain.com/artisan/api/{command}/{subcommand}?args=key1:value1,key2:value2&options=opt1:value1,opt2
So the above endpoint will be translated to:
php artisan command:subcommand value1 value2 --opt1=value1 --opt2
And for Generator commands the endpoint is:
https://domain.com/artisan/api/{command}/{subcommand}/{name}?args=key1:value1,key2:value2&options=opt1:value1,opt2
Pay attention that there is a name
variable. As all Generator commands need an argument called name
, this needs to be specified by what you desire.
Command Examples:
php artisan list
will be translated to:
https://domain.com/artisan/api/list
and this:
php artisan cache:forget myCachedKeyName
will be translated to:
https://domain.com/artisan/api/cache/forget?args=key:myCachedKeyName
Another one:
php artisan optimize:clear -v
will be translated to:
https://domain.com/artisan/api/optimize/clear?options=v
A Generator one:
php artisan make:model MyModel --controller -f
will be translated to:
https://domain.com/artisan/api/make/model/MyModel?options=controller,f
Options with more than one character will be translated to
--option
.
After calling an endpoint, you will receive a `` response.
When everything works perfectly: status : 200 OK
{
"ok": true,
"status": 200,
"output": "Output of the command, given by Artisan"
}
When inputed command is not found by application: status : 404 Not Found
{
"ok": false,
"status": 404,
"output": "Command 'command:subcommand' is not defined."
}
When arguments are given by an invalid format: status : 500 Server Error
{
"ok": false,
"status": 500,
"output": "Argument(s) 'key:value' given by an invalid format."
}
When options are given by an invalid format: status : 500 Server Error
{
"ok": false,
"status": 500,
"output": "Options(s) 'key:value' given by an invalid format."
}
You might want to limit access to some critical commands like db:seed
. Artisan-Api has thought about it and make those commands inaccessible by client.
To specify forbidden commands, you are encouraged to add them within config/artisan.php
file:
return [
...,
'forbidden-routes' => [
'clear-compiled',
'tinker',
'up',
'down',
'serve',
'completion',
'_complete',
'db*', // all `db:seed` and `db:wipe` will be inaccessible
'*publish' // like `vendor:publish`
]
];
Whenever client wants to access these commands by endpoints, it will be given a 404 NOT_FOUND
HTTP response.
All enpoints will be generated under the api
middleware of Laravel and prevented by built-in authentication system, mostly with Sanctum
and API tokens.
As mentioned before, there is a configuration config/artisan.php
file.
You are free to modify specified values as you desire.
Here, it is possible to change default API prefix and customize it as necessary. In addition you can access endpoints with any HTTP method as you set.
return [
...
'api' => [
'prefix' => "/artisan/api",
'method' => 'POST', // or ['POST', 'PUT']
],
...
];
For some reason and mostly on production mode, you do not want to allow commands to be executed by HTTP request. To prevent this behavior, set that auto-run
to false
:
return [
...
'auto-run' => false,
...
];
This prevents not to load package's service-provider (ArtisanApiServiceProvider
) by default.
Artisan-Api has done its best to protect RCE vulnerability and other possible logical bugs.
Artisan-Api uses
Symfony/console
under the hood and all commands execution are filtered and recognized by it. There is no direct call toshell_exec()
orexec()
functions.
You can simply allow as many IP as you want to access to your commands. '*'
means all IPs are trusted.
There are two middlewares in Artisan-Api.
CheckEnvMode
middleware exists to abort requests while in production environment.
AbortForbiddenRoute
middleware exists to throw 404 NOT_FOUND
status code while accessing to forbidden routes.
;)
- It'd better be done to take
args
andoptions
in query string, to be array.- Like:
?arg[key1]=value1&arg[key2]=value2
(it is a more standard way to deal with query string values)
- Like:
- Implement a way to deal with interactive commands like
tinker
(maybe can be implemented by socket) - Make response more readable for users, (remove "\n", ...)