Completed
Push — 1.0 ( efa4d7 )
by Yuichi
07:23
created

FinishMiddleware::createException()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 13
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 13
rs 9.4285
c 0
b 0
f 0
cc 3
eloc 8
nc 3
nop 3
1
<?php
2
3
namespace CybozuHttp\Middleware;
4
5
use GuzzleHttp\Exception\ClientException;
6
use GuzzleHttp\Exception\RequestException;
7
use GuzzleHttp\Exception\ServerException;
8
use Psr\Http\Message\RequestInterface;
9
use Psr\Http\Message\ResponseInterface;
10
11
/**
12
 * @author ochi51 <[email protected]>
13
 */
14
class FinishMiddleware
15
{
16
17
    /**
18
     * Called when the middleware is handled by the client.
19
     *
20
     * @param callable $handler
21
     *
22
     * @return \Closure
23
     */
24
    public function __invoke(callable $handler)
25
    {
26
        return function ($request, array $options) use ($handler) {
27
28
            return $handler($request, $options)->then(
29
                $this->onFulfilled($request),
30
                $this->onRejected($request)
31
            );
32
        };
33
    }
34
35
    /**
36
     * @param RequestInterface $request
37
     * @return \Closure
38
     */
39
    private function onFulfilled(RequestInterface $request)
40
    {
41
        return function (ResponseInterface $response) use ($request) {
42
            return $response->withBody(new JsonStream($response->getBody()));
43
        };
44
    }
45
46
    /**
47
     * @param RequestInterface $request
48
     * @return \Closure
49
     */
50
    private function onRejected(RequestInterface $request)
51
    {
52
        return function ($reason) use ($request) {
53
            if ($reason instanceof RequestException) {
54
                $response = $reason->getResponse();
55
                if ($response && $response->getStatusCode() >= 300) {
56
                    self::jsonError($request, $response);
57
                    self::domError($request, $response);
58
                }
59
            }
60
        };
61
    }
62
63
    /**
64
     * @param RequestInterface $request
65
     * @param ResponseInterface $response
66
     */
67
    private static function domError(RequestInterface $request, ResponseInterface $response)
68
    {
69
        $body = (string)$response->getBody();
70
        $dom = new \DOMDocument('1.0', 'UTF-8');
71
        $dom->preserveWhiteSpace = false;
72
        $dom->formatOutput = true;
73
        $dom->loadHTML($body);
74
        if ($dom->loadHTML($body)) {
75
            $title = $dom->getElementsByTagName('title');
76
            if (is_object($title)) {
77
                $title = $title->item(0)->nodeValue;
78
            }
79
            if ($title === 'Error') {
80
                $message = $dom->getElementsByTagName('h3')->item(0)->nodeValue;
81
                throw self::createException($message, $request, $response);
82
            }
83
            if ($title === 'Unauthorized') {
84
                $message = $dom->getElementsByTagName('h2')->item(0)->nodeValue;
85
                throw self::createException($message, $request, $response);
86
            }
87
88
            throw self::createException('Invalid auth.', $request, $response);
89
        }
90
    }
91
92
    /**
93
     * @param RequestInterface $request
94
     * @param ResponseInterface $response
95
     */
96
    private static function jsonError(RequestInterface $request, ResponseInterface $response)
97
    {
98
        try {
99
            $body = (string)$response->getBody();
100
            $json = json_decode($body, true);
101
            if (json_last_error() !== JSON_ERROR_NONE) {
102
                throw new \RuntimeException(
103
                    'Error trying to decode response: ' .
104
                    json_last_error_msg()
105
                );
106
            }
107
        } catch (\RuntimeException $e) {
108
            return;
109
        }
110
111
        $message = $json['message'];
112
        if (isset($json['errors']) && is_array($json['errors'])) {
113
            $message .= self::addErrorMessages($json['errors']);
114
        }
115
116
        throw self::createException($message, $request, $response);
117
    }
118
119
    /**
120
     * @param array $errors
121
     * @return string
122
     */
123
    private static function addErrorMessages(array $errors)
124
    {
125
        $message = ' (';
126
        foreach ($errors as $k => $err) {
127
            $message .= $k . ' : ';
128
            if (is_array($err['messages'])) {
129
                foreach ($err['messages'] as $m) {
130
                    $message .= $m . ' ';
131
                }
132
            } else {
133
                $message .= $err['messages'];
134
            }
135
        }
136
        $message .= ' )';
137
138
        return $message;
139
    }
140
141
    /**
142
     * @param string $message
143
     * @param RequestInterface $request
144
     * @param ResponseInterface|null $response
145
     * @return RequestException
146
     */
147
    private static function createException($message, RequestInterface $request, ResponseInterface $response)
148
    {
149
        $level = (int) floor($response->getStatusCode() / 100);
150
        $className = RequestException::class;
151
152
        if ($level === 4) {
153
            $className = ClientException::class;
154
        } elseif ($level === 5) {
155
            $className = ServerException::class;
156
        }
157
158
        return new $className($message, $request, $response);
159
    }
160
}