Completed
Push — master ( 039bdb...90d49c )
by Yuichi
11s
created

FinishMiddleware::onRejected()   A

Complexity

Conditions 4
Paths 1

Size

Total Lines 12
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 4.1755

Importance

Changes 0
Metric Value
dl 0
loc 12
ccs 7
cts 9
cp 0.7778
rs 9.2
c 0
b 0
f 0
cc 4
eloc 7
nc 1
nop 1
crap 4.1755
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 52
    public function __invoke(callable $handler)
25
    {
26
        return function ($request, array $options) use ($handler) {
27
28 52
            return $handler($request, $options)->then(
29 52
                $this->onFulfilled($request),
30 52
                $this->onRejected($request)
31 52
            );
32 3
        };
33
    }
34
35
    /**
36
     * @param RequestInterface $request
37
     * @return \Closure
38
     */
39 52
    private function onFulfilled(RequestInterface $request)
40
    {
41
        return function (ResponseInterface $response) use ($request) {
42 52
            return $response->withBody(new JsonStream($response->getBody()));
43 52
        };
44
    }
45
46
    /**
47
     * @param RequestInterface $request
48
     * @return \Closure
49
     */
50
    private function onRejected(RequestInterface $request)
51
    {
52 52
        return function ($reason) use ($request) {
53 5
            if ($reason instanceof RequestException) {
54 5
                $response = $reason->getResponse();
55 5
                if ($response && $response->getStatusCode() >= 300) {
56 5
                    self::jsonError($request, $response);
57 1
                    self::domError($request, $response);
58
                }
59
            }
60 52
        };
61
    }
62
63
    /**
64
     * @param RequestInterface $request
65
     * @param ResponseInterface $response
66
     */
67 1
    private static function domError(RequestInterface $request, ResponseInterface $response)
68
    {
69 1
        $body = (string)$response->getBody();
70 1
        $dom = new \DOMDocument('1.0', 'UTF-8');
71 1
        $dom->preserveWhiteSpace = false;
72 1
        $dom->formatOutput = true;
73 1
        $dom->loadHTML($body);
74 1
        if ($dom->loadHTML($body)) {
75 1
            $title = $dom->getElementsByTagName('title');
76 1
            if (is_object($title)) {
77 1
                $title = $title->item(0)->nodeValue;
78 1
            }
79 1
            if ($title === 'Error') {
80 1
                $message = $dom->getElementsByTagName('h3')->item(0)->nodeValue;
81 1
                throw self::createException($message, $request, $response);
82
            }
83 1
            if ($title === 'Unauthorized') {
84 1
                $message = $dom->getElementsByTagName('h2')->item(0)->nodeValue;
85 1
                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 5
    private static function jsonError(RequestInterface $request, ResponseInterface $response)
97
    {
98
        try {
99 5
            $body = (string)$response->getBody();
100 5
            $json = json_decode($body, true);
101 5
            if (json_last_error() !== JSON_ERROR_NONE) {
102 1
                throw new \RuntimeException(
103
                    'Error trying to decode response: ' .
104 1
                    json_last_error_msg()
105 1
                );
106
            }
107 5
        } catch (\RuntimeException $e) {
108 1
            return;
109
        }
110
111 4
        $message = $json['message'];
112 4
        if (isset($json['errors']) && is_array($json['errors'])) {
113
            $message .= self::addErrorMessages($json['errors']);
114
        }
115
116 4
        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 5
    private static function createException($message, RequestInterface $request, ResponseInterface $response)
148
    {
149 5
        $level = (int) floor($response->getStatusCode() / 100);
150 5
        $className = RequestException::class;
151
152 5
        if ($level === 4) {
153 1
            $className = ClientException::class;
154 5
        } elseif ($level === 5) {
155 5
            $className = ServerException::class;
156 5
        }
157
158 5
        return new $className($message, $request, $response);
159
    }
160
}