# node-php-awesome-server

> Create a fast php server for your development using node and workers.

Latest version **1.5.0** (published 2021-07-29) · MIT license · 0 weekly downloads

## Install

```sh
npm install node-php-awesome-server
pnpm add node-php-awesome-server
yarn add node-php-awesome-server
bun add node-php-awesome-server
```

## Health

**Score 25/100 (F)** — status: abandoned.

Positive: has types; no vulnerabilities; high quality score.

Warnings: low downloads; no esm support.

Negative: abandoned; low maintenance score.

## Facts

| | |
|---|---|
| Version | 1.5.0 |
| Published | 2021-07-29 |
| First published | 2017-06-17 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | bundled |
| Module format | CommonJS |
| Dependencies | 8 |
| Unpacked size | 3.7 MB |
| Known vulnerabilities | 0 (+1 in 1 direct dependencies) |
| Install scripts | no |
| Author | darklightcode |
| Maintainers | darklightcode |
| Keywords | node php server, php, node server, php server, node php awesome server, node, server, awesome, awesome server, php-built-in-web-server-router |

## Links

- npm: https://www.npmjs.com/package/node-php-awesome-server
- npm.io page: https://npm.io/package/node-php-awesome-server

## Dependencies (8)

- [cors](https://npm.io/package/cors.md) ^2.8.5
- [chalk](https://npm.io/package/chalk.md) ^4.1.1
- [express](https://npm.io/package/express.md) ^4.17.1
- [request](https://npm.io/package/request.md) ^2.83.0
- [dateformat](https://npm.io/package/dateformat.md) ^4.5.1
- [ua-parser2](https://npm.io/package/ua-parser2.md) ^0.5.1
- [node-port-check](https://npm.io/package/node-port-check.md) ^2.0.1
- [php-built-in-web-server-router](https://npm.io/package/php-built-in-web-server-router.md) ^1.6.1

## Alternatives

- [@expo/fingerprint](https://npm.io/package/@expo/fingerprint.md) — 6.2M weekly downloads
- [@azure/monitor-opentelemetry-exporter](https://npm.io/package/@azure/monitor-opentelemetry-exporter.md) — 850.0K weekly downloads
- [@azure/monitor-opentelemetry](https://npm.io/package/@azure/monitor-opentelemetry.md) — 624.0K weekly downloads
- [@posthog/ai](https://npm.io/package/@posthog/ai.md) — 423.3K weekly downloads
- [fakefilter](https://npm.io/package/fakefilter.md) — 63.9K weekly downloads

## Recent versions

- 1.5.0 (latest) — 2021-07-29
- 1.4.0 — 2021-01-19
- 1.3.1 — 2017-12-19
- 1.3.0 — 2017-12-18
- 1.2.9 — 2017-12-11
- 1.2.6 — 2017-12-08
- 1.2.5 — 2017-12-08
- 1.2.4 — 2017-12-07
- 1.2.2 — 2017-12-07
- 1.1.5 — 2017-08-04
- 1.1.4 — 2017-07-26
- 1.1.3 — 2017-07-26
- 1.1.2 — 2017-07-17
- 1.1.1 — 2017-07-17
- 1.1.0 — 2017-07-17
- … 1 more at https://npm.io/package/node-php-awesome-server/versions

## README

# Node PHP Awesome Server
![Node PHP Awesome Server](https://raw.githubusercontent.com/darklightcode/PHP-Built-in-web-server-Router/master/src/logo.png)
```
npm install node-php-awesome-server --save-dev
```
# Update

1.5.0 :
----------------
- Updated dependencies
- Minor adjustments

1.4.0 :
----------------
- Dependencies were upgraded in this update !
- Note: A major upgrade will be issued in the following months, the project was refactored, many bugs were fixed, and will come with some big features which will allow you more control over the environment.

1.3.1 :
----------------
- Added new option ```middlewareAfter```, same as ```middleware```, but registered after the request to php is done.
- Exposed objects ```res.locals.phpBody``` (Buffer) and ```res.locals.phpHeaders``` . Available only in middlewares registered in ```middlewareAfter```.

1.3.0 :
----------------
- Fixed an issue where cookies were not kept between master and workers.

1.2.12 :
----------------
- Fixed an issue where cookies where not kept.

1.2.9 :
----------------
- Fixed an issue where Apache/Nginx would take over if the worker would target an undefined port.

1.2.4 :
----------------
- added middleware support
- added php instances to workers ( see phpPerCluster )
- added to `output` the following options : `reqTime` and `port`,
- now you can **cURL** on the same project
- changed strategy for request distribution
- added option `ini_config` so you can load your own php.ini


# Use it if you want:
1. A fast local development PHP Server benefiting the advantages from [php-built-in-web-server-router](https://www.npmjs.com/package/php-built-in-web-server-router) 
2. Multiple workers for a faster serving time.
3. A colorful output.

# Options
**Options** | **Default** | **Description**
------- | -------------- | -----------
host | 0.0.0.0 | Your local IP address
port | 9000 | Your local port
root    |   ./src/public    |   Path to your folder with index.php
bin |   php |   CLI command to trigger php
ini_config |    |   Load a custom php.ini file. Requires an absolute path to the file.<br />**NOTE: ini_set can override values from any config.ini**
ini_set |   {}  |   Allows you to set INI directives by adding key:value pairs, including runtime entries (PHP_INI_SYSTEM). 'curl.cainfo' is being added by default if it isn't set
clusterSet  |   auto    |   'Auto' will create a number of workers based on your cpu's(i highly recommend 'auto'), you can specify an integer value if you want but BEWARE of the number of workers that exceeds the number of CPU's
phpPerCluster   | 'based on clusterSet'  |  Number of PHP instances allocated to each cluster. If clusterSet=1 then the minimum default value of phpPerCluster is 2. If clusterSet>1 then the minimum default value of phpPerCluster is 1
secureOrigin    |   true    | By default - true - will keep HTTP_HOST in your PHP requests even if you're being proxied. Leave it TRUE or start debugging - MAKE YOUR CHOICE
theme   |   php |   'php', 'angular', 'react', 'codeigniter' - This feature is mostly for esthetics and will change the theme if 'root', 'router' and 'indexFile' are set to default.
router  |   **php-built-in-web-server-router** | If you don't specify the 'router', it's taken care of by the default router file. By using the default router you will have an aditional option to change 'index.php' to something else.
indexFile | index.php   | You can point the router to load other 'index' or 'php' file(e.g. index.html , myNewIndex.php, someOtherFile.htm). This option works only if the 'router' option isn't specified.
env |   {}  | Add key:value pairs that you can use in your PHP later with $_SERVER['KEY']
middleware  | (req,res,next)=>{next()}  |   Bind a middleware to the server, you can use a function or an array of functions
middlewareAfter  | (req,res,next)=>{next()}  |   It's the same as ```middleware``` but registered after the request is done and will populate ```res.locals``` with ```res.locals.phpBody``` and ```res.locals.phpHeaders```
**output**  | **Object** | **see below values**
output.startup  |  true | Console info about the starting process
output.date |   true    |   Request date
output.ip   |   true    |   Request IP
output.os   |   false    |   Request Platform
output.browser   |   false    |   Request Browser
output.device   |   false    |   Request Device
output.statusCode   |   true    |   Request http status code
output.method   |   true    |   Request http method
output.reqTime   |   false    |   Request duration
output.port   |   false    |   Show the PHP port that served the request

# Events
**Event** | **Description**
------- | -----------
connect |   All workers are up and running
close   |   Kill all the workers and close the server

# Middleware:
The middleware option supports the following formats:
- a function
- an array with [path, function]
- an array with the above formats

# MiddlewareAfter:
Bellow there are two examples that change output, both of them use ```cheerio``` to edit the markup:

Keep in mind that ```res.locals.phpBody``` is a **Buffer** and in the end it is the output you will see.

Example 1 - Alter body and end all (any middlewares after this won't get processed):
```
function(req,res){
 
     /**
      * Get the body
      */
     var body = res.locals.phpBody;
     
     /**
      * Target only content-type text/html
      */
     if (res.locals.phpHeaders.hasOwnProperty('content-type') && res.locals.phpHeaders['content-type'].indexOf('text/html') !== -1) {
    
         var baseUrl = req.protocol + '://' + req.headers['host'] + "/";
         
         /**
          * Convert body to string => body.toString() , and pass it to cheerio
          */
         var $ = require('cheerio').load(body.toString());
    
         $("body").append('<div>this tag is from node : '+baseUrl+'</div>')
        
         body = $.html();
    
     }
    
     /**
      * End request
      */
     res.end(body);

}
```
Example 2 - Alter body and continue:
```
function(req,res,next){
 
     /**
      * Get the body
      */
     var body = res.locals.phpBody;
     
     /**
      * Target only content-type text/html
      */
     if (res.locals.phpHeaders.hasOwnProperty('content-type') && res.locals.phpHeaders['content-type'].indexOf('text/html') !== -1) {
    
         var baseUrl = req.protocol + '://' + req.headers['host'] + "/";
         
         /**
          * Convert body to string => body.toString() , and pass it to cheerio
          */
         var $ = require('cheerio').load(body.toString());
    
         $("body").append('<div>this tag is from node : '+baseUrl+'</div>')
                
         body = $.html();
    
     }
    
     /**
      * Continue with the next middleware
      */
     res.locals.phpBody = body
     
     next();
     
}
```


# Use the default Router if you:
- want caching ( see the output bellow for 304 status )
- want to point the router to another 'index.php' file
- don't have any router files

# Caveats
Using multiple instances of the same CMS(Wordpress, Drupal, etc. - usually those that use cookies) on the same PORT may show you some 403 (Forbidden) status codes. You can fix this by deleting your cookies.

### Example
```javascript
const simpleMiddleware = (req, res, next) => {

    if (!req.app.hasOwnProperty('output_once')) {

        req.app['output_once'] = true;
        console.log("Simple Middleware - I trigger once before the first request")

    }

    next();

};

const fontsMiddleware = (req, res, next) => {

    console.log("I'll appear only when you're locating the /fonts/ url");

    next();
};

const nodePhpAwesomeServer = require('node-php-awesome-server');

const php = nodePhpAwesomeServer({

    port: 9012,
    env: {
        'SOMEKEY': 'some value',
        'customObject': JSON.stringify({'test':0,'name':'yes'})
    },
    middleware: [
            /**
             * Just the middleware
             */
            simpleMiddleware,
    
            /**
             * Path and middleware
             */
            ["/fonts/*", fontsMiddleware]
        ],
    //ini_config: "/path/to/your/custom.ini",
    ini_set: {
        max_execution_time: 280
    },
    output: {
        os: true,
        browser: true,
        device: true,
        reqTime: true
    },
    clustersSet: 'auto',
    phpPerCluster: 2

});

php.on('close', () => {
    console.log('php server closed');
});

php.on('connect', () => {

    console.log('All up and running');

    //php.close();

});

//php.close();

```
**Run**
```
node ./YOUR_FILE_WITH_THE_ABOVE_CODE.js
```

**Output:**
```
> node ./test/example.js

Worker 3 hired - PID 16096
Worker 1 hired - PID 240
Worker 2 hired - PID 19924
DOCUMENT ROOT: D:/Projects/Home/Workspace/Sites/node-php-awesome-server/public
ROUTER: default
LINK: http://localhost:9012
EXTERNAL: http://192.168.0.35:9012
Simple Middleware - I trigger once before the first request
[W2] [Thu Dec 07 2017 18:28:31 2017] 127.0.0.1:57268 [Windows 10] [Firefox] [Other] [200][GET] [58ms]: /
[W2] [Thu Dec 07 2017 18:28:31 2017] 127.0.0.1:57272 [Windows 10] [Firefox] [Other] [304][GET] [38ms]: /polyfills.bundle.js
[W1] [Thu Dec 07 2017 18:28:31 2017] 127.0.0.1:57273 [Windows 10] [Firefox] [Other] [304][GET] [40ms]: /vendor.bundle.js
[W2] [Thu Dec 07 2017 18:28:31 2017] 127.0.0.1:57271 [Windows 10] [Firefox] [Other] [304][GET] [48ms]: /style.css
[W3] [Thu Dec 07 2017 18:28:31 2017] 127.0.0.1:57275 [Windows 10] [Firefox] [Other] [304][GET] [63ms]: /app.bundle.js
[W2] [Thu Dec 07 2017 18:28:31 2017] 127.0.0.1:57283 [Windows 10] [Firefox] [Other] [304][GET] [25ms]: /images/icon.php5.e030bb780de676e424e3a975ea89e83c.png
[W2] [Thu Dec 07 2017 18:29:32 2017] 127.0.0.1:57289 [Windows 10] [Firefox] [Other] [200][GET] [34ms]: /
[W2] [Thu Dec 07 2017 18:29:32 2017] 127.0.0.1:57296 [Windows 10] [Firefox] [Other] [200][GET] [38ms]: /app.bundle.js
[W2] [Thu Dec 07 2017 18:29:32 2017] 127.0.0.1:57294 [Windows 10] [Firefox] [Other] [200][GET] [77ms]: /polyfills.bundle.js
[W2] [Thu Dec 07 2017 18:29:32 2017] 127.0.0.1:57292 [Windows 10] [Firefox] [Other] [200][GET] [174ms]: /style.css
I'll appear only when you're locating the /fonts/ url
[W3] [Thu Dec 07 2017 18:29:32 2017] 127.0.0.1:57304 [Windows 10] [Firefox] [Other] [200][GET] [47ms]: /fonts/Roboto-Light.46e48ce0628835f68a7369d0254e4283.ttf
[W2] [Thu Dec 07 2017 18:29:32 2017] 127.0.0.1:57295 [Windows 10] [Firefox] [Other] [200][GET] [394ms]: /vendor.bundle.js
[W1] [Thu Dec 07 2017 18:29:33 2017] 127.0.0.1:57307 [Windows 10] [Firefox] [Other] [200][GET] [25ms]: /images/icon.php5.e030bb780de676e424e3a975ea89e83c.png
```
**You will see each request starts with [W3][W1]...[Wx]), these are the Workers serving requests**

**Open the server link on multiple browsers if you wanna see different workers, or you can just spam with some ajax the server link**

---
_Source: https://npm.io/package/node-php-awesome-server · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
