Skip to content

Commit d86f295

Browse files
committed
wip
0 parents  commit d86f295

File tree

11 files changed

+683
-0
lines changed

11 files changed

+683
-0
lines changed

.gitignore

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
# Laravel
2+
/vendor
3+
/node_modules
4+
/public/storage
5+
/storage/*.key
6+
.env
7+
Homestead.yaml
8+
Homestead.json
9+
.idea
10+
.phpunit.result.cache
11+
/.vscode
12+
/.idea
13+
/.DS_Store
14+
15+
# NPM
16+
npm-debug.log
17+
yarn-error.log
18+
19+
# Composer
20+
composer.lock
21+
composer.phar
22+
23+
# IDEs and Editors
24+
*.swp
25+
*.swo
26+
*.sublime-project
27+
*.sublime-workspace
28+
29+
# Laravel-specific
30+
bootstrap/cache/*
31+
storage/app/*
32+
storage/framework/*
33+
storage/logs/*
34+
public/storage
35+
36+
# Laravel 8 and later
37+
.env.local
38+
.env.*.local
39+
40+
# Package-related
41+
/vendor/*
42+
/node_modules/*
43+
/composer.lock
44+
45+
# Miscellaneous
46+
*.log
47+
*.tmp
48+
*.cache
49+
50+
# OS-specific
51+
.DS_Store
52+
Thumbs.db
53+
54+
# Local environment files
55+
*.local

README.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Laravel Response Builder
2+
3+
A Laravel package designed to simplify the creation of structured and formatted API responses (JSON, XML) with custom status codes, messages, and data.
4+
5+
## Installation
6+
7+
Install via Composer:
8+
9+
```bash
10+
composer require d-oliveira/laravel-response-builder
11+
```

composer.json

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
{
2+
"name": "doliveira/laravel-api-response-builder",
3+
"version": "1.0.0",
4+
"description": "A Laravel package designed to simplify the creation of structured and formatted API responses (JSON, XML) with custom status codes, messages, and data.",
5+
"type": "library",
6+
"license": "MIT",
7+
"minimum-stability": "stable",
8+
"prefer-stable": true,
9+
"homepage": "https://github.com/DaniloWA/laravel-api-response-builder",
10+
"keywords": [
11+
"doliveira",
12+
"danilo",
13+
"oliveira",
14+
"laravel-api-response-builder",
15+
"api-response-builder",
16+
"api-response",
17+
"response-builder",
18+
"laravel",
19+
"api",
20+
"response",
21+
"json",
22+
"xml",
23+
"package"
24+
],
25+
"authors": [
26+
{
27+
"name": "Danilo Oliveira",
28+
"email": "daniloworkdev@gmail.com",
29+
"homepage": "http://www.daniloo.dev",
30+
"role": "Developer"
31+
}
32+
],
33+
"require": {
34+
"php": "^7.3|^8.0|^8.1|^8.2",
35+
"laravel/framework": "^8.12|^9.0|^10.0|^11.0"
36+
},
37+
"autoload": {
38+
"psr-4": {
39+
"Doliveira\\LaravelResponseBuilder\\": "src/",
40+
"Doliveira\\LaravelResponseBuilder\\Providers\\": "src/providers/",
41+
"Doliveira\\LaravelResponseBuilder\\Resources\\": "src/resources",
42+
"Doliveira\\LaravelResponseBuilder\\Config\\": "src/config"
43+
}
44+
},
45+
"autoload-dev": {
46+
"psr-4": {
47+
"Doliveira\\LaravelResponseBuilder\\Tests\\": "tests"
48+
}
49+
},
50+
"extra": {
51+
"laravel": {
52+
"providers": [
53+
"Doliveira\\LaravelResponseBuilder\\Providers\\ResponseBuilderServiceProvider"
54+
]
55+
}
56+
},
57+
"config": {
58+
"sort-packages": true,
59+
"optimize-autoloader": true,
60+
"preferred-install": "dist"
61+
}
62+
}

src/BaseResponse.php

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
<?php
2+
3+
namespace Doliveira\LaravelResponseBuilder;
4+
5+
use Illuminate\Support\Facades\Config;
6+
7+
abstract class BaseResponse
8+
{
9+
protected $statusCode;
10+
protected $message;
11+
protected $data;
12+
13+
public function __construct($statusCode = null, $message = null, $data = null)
14+
{
15+
$this->statusCode = $statusCode ?? Config::get('responsebuilder.default_status_code');
16+
$this->message = $message;
17+
$this->data = $data;
18+
}
19+
20+
protected function getResponseStructure(): array
21+
{
22+
return Config::get('responsebuilder.custom_response_structure', [
23+
'status' => 'status',
24+
'message' => 'message',
25+
'data' => 'data'
26+
]);
27+
}
28+
29+
protected function wrapData($data): array
30+
{
31+
if (Config::get('responsebuilder.wrap_data', true)) {
32+
return ['data' => $data];
33+
}
34+
35+
return $data;
36+
}
37+
38+
protected function getJsonOptions(): int
39+
{
40+
return Config::get('responsebuilder.json_options', JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
41+
}
42+
43+
protected function getCompressionSetting(): bool
44+
{
45+
return Config::get('responsebuilder.compress_responses', false);
46+
}
47+
48+
protected function getLoggingSetting(): bool
49+
{
50+
return Config::get('responsebuilder.log_responses', false);
51+
}
52+
53+
protected function getLoggingLevel(): string
54+
{
55+
return Config::get('responsebuilder.logging_level', 'info');
56+
}
57+
58+
protected function getCorsSettings(): array
59+
{
60+
return Config::get('responsebuilder.cors_settings', []);
61+
}
62+
63+
protected function getDetailedErrors(): bool
64+
{
65+
return Config::get('responsebuilder.detailed_errors', false);
66+
}
67+
68+
protected function getDefaultResponseLanguage(): string
69+
{
70+
return Config::get('responsebuilder.default_response_language', 'en');
71+
}
72+
73+
protected function getApiKeyHeader(): string
74+
{
75+
return Config::get('responsebuilder.api_key_header', 'X-API-KEY');
76+
}
77+
78+
protected function getDebugMode(): bool
79+
{
80+
return Config::get('responsebuilder.debug_mode', false);
81+
}
82+
}

src/JsonResponse.php

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
<?php
2+
3+
namespace Doliveira\LaravelResponseBuilder;
4+
5+
use Illuminate\Http\JsonResponse as IlluminateJsonResponse;
6+
use Illuminate\Support\Facades\Lang;
7+
8+
class JsonResponse extends BaseResponse
9+
{
10+
public static function success($data = null, $message = null): IlluminateJsonResponse
11+
{
12+
$message = $message ?? Lang::get('response.success');
13+
return (new self(200, $message, $data))->buildResponse();
14+
}
15+
16+
public static function error($statusCode, $message = null, $data = null): IlluminateJsonResponse
17+
{
18+
$message = $message ?? Lang::get('response.server_error');
19+
return (new self($statusCode, $message, $data))->buildResponse();
20+
}
21+
22+
public static function auto($statusCode, $message = null, $data = null): IlluminateJsonResponse
23+
{
24+
return (new self($statusCode, $message, $data))->buildResponse();
25+
}
26+
27+
public function buildResponse(): IlluminateJsonResponse
28+
{
29+
LogResponse::logRequest();
30+
31+
$startTime = microtime(true);
32+
33+
$structure = $this->getResponseStructure();
34+
$response = [
35+
$structure['status'] => $this->statusCode,
36+
$structure['message'] => $this->message,
37+
$structure['data'] => $this->wrapData($this->data),
38+
];
39+
40+
$jsonOptions = $this->getJsonOptions();
41+
$jsonResponse = json_encode($response, $jsonOptions);
42+
43+
if ($this->getCompressionSetting()) {
44+
$jsonResponse = gzcompress($jsonResponse);
45+
}
46+
47+
if ($this->getLoggingSetting()) {
48+
LogResponse::log(new IlluminateJsonResponse($jsonResponse, $this->statusCode));
49+
}
50+
51+
$response = response()->json($response, $this->statusCode);
52+
53+
LogResponse::logResponseTime($startTime);
54+
55+
return $response;
56+
}
57+
}

src/LogResponse.php

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
<?php
2+
3+
namespace Doliveira\LaravelResponseBuilder;
4+
5+
use Illuminate\Http\JsonResponse as IlluminateJsonResponse;
6+
use Illuminate\Support\Facades\Config;
7+
use Illuminate\Support\Facades\Log;
8+
use Illuminate\Support\Facades\Request;
9+
10+
class LogResponse
11+
{
12+
/**
13+
* Log the response details.
14+
*
15+
* @param IlluminateJsonResponse $response
16+
* @return void
17+
*/
18+
public static function log(IlluminateJsonResponse $response): void
19+
{
20+
$validLevels = ['emergency', 'alert', 'critical', 'error', 'warning', 'notice', 'info', 'debug'];
21+
$level = Config::get('responsebuilder.logging_level', 'info');
22+
23+
if (!in_array($level, $validLevels, true)) {
24+
$level = 'info'; // Default level
25+
}
26+
27+
// Collect log data
28+
$logData = [
29+
'status' => $response->status(),
30+
'headers' => $response->headers->all(),
31+
'content' => self::sanitizeContent($response->getContent()), // Sanitize content
32+
];
33+
34+
// Format the log data
35+
$formattedLog = json_encode($logData, JSON_PRETTY_PRINT);
36+
37+
// Log the response if enabled
38+
if (Config::get('responsebuilder.log_responses', false)) {
39+
Log::$level($formattedLog);
40+
}
41+
}
42+
43+
/**
44+
* Log the request details.
45+
*
46+
* @return void
47+
*/
48+
public static function logRequest(): void
49+
{
50+
if (!Config::get('responsebuilder.log_requests', false)) {
51+
return;
52+
}
53+
54+
$request = Request::instance();
55+
56+
// Collect log data
57+
$logData = [
58+
'method' => $request->method(),
59+
'url' => $request->fullUrl(),
60+
'headers' => $request->headers->all(),
61+
'body' => $request->all(),
62+
];
63+
64+
// Format the log data
65+
$formattedLog = json_encode($logData, JSON_PRETTY_PRINT);
66+
67+
// Log the request
68+
Log::info('Request Data: ' . $formattedLog);
69+
}
70+
71+
/**
72+
* Log the response time.
73+
*
74+
* @param float $startTime
75+
* @return void
76+
*/
77+
public static function logResponseTime(float $startTime): void
78+
{
79+
if (!Config::get('responsebuilder.log_response_time', false)) {
80+
return;
81+
}
82+
83+
$endTime = microtime(true);
84+
$responseTime = $endTime - $startTime;
85+
86+
// Collect log data
87+
$logData = [
88+
'response_time' => number_format($responseTime * 1000, 2) . ' ms', // Convert to milliseconds
89+
];
90+
91+
// Format the log data
92+
$formattedLog = json_encode($logData, JSON_PRETTY_PRINT);
93+
94+
// Log the response time
95+
Log::info('Response Time: ' . $formattedLog);
96+
}
97+
98+
/**
99+
* Sanitize response content to remove sensitive information.
100+
*
101+
* @param string $content
102+
* @return string
103+
*/
104+
private static function sanitizeContent(string $content): string
105+
{
106+
$decodedContent = json_decode($content, true);
107+
108+
// Example: Remove sensitive information
109+
if (isset($decodedContent['data']['token'])) {
110+
$decodedContent['data']['token'] = '***REDACTED***';
111+
}
112+
113+
return json_encode($decodedContent, JSON_PRETTY_PRINT);
114+
}
115+
}

0 commit comments

Comments
 (0)