HTTPClient.php
1 <?php
2 /**
3  * wCMF - wemove Content Management Framework
4  * Copyright (C) 2005-2020 wemove digital solutions GmbH
5  *
6  * Licensed under the terms of the MIT License.
7  *
8  * See the LICENSE file distributed with this work for
9  * additional information.
10  */
11 namespace wcmf\lib\service\impl;
12 
19 
20 if (!class_exists('Zend_Http_Client')) {
21  throw new ConfigurationException(
22  'wcmf\lib\service\impl\HTTPClient requires '.
23  'Zend_Http_Client. If you are using composer, add zf1/zend-http '.
24  'as dependency to your project');
25 }
26 
27 /**
28  * HTTPClient is used to do calls to other wCMF instances over HTTP.
29  * @see RemotingServer
30  *
31  * @note This class requires Zend_Http_Client
32  *
33  * @author ingo herwig <ingo@wemove.com>
34  */
35 class HTTPClient implements RemotingClient {
36 
37  private static $logger = null;
38 
39  private $client = null;
40  private $user = null;
41  private $sessionId = null;
42  private $serverUrl = null;
43 
44  /**
45  * Constructor
46  * @param $serverUrl The url of the other server instance.
47  * @param $user The remote user instance.
48  */
49  public function __construct($serverUrl, $user) {
50  if (self::$logger == null) {
51  self::$logger = LogManager::getLogger(__CLASS__);
52  }
53  $this->serverUrl = $serverUrl;
54  $this->client = new Zend_Http_Client($this->serverUrl, [
55  'keepalive' => true,
56  'timeout' => 3600
57  ]);
58  $this->client->setMethod(Zend_Http_Client::POST);
59  $this->client->setCookieJar();
60  $this->user = $user;
61  }
62 
63  /**
64  * Do a call to the remote server.
65  * @param $request A Request instance
66  * @return A Response instance
67  */
68  public function call(Request $request) {
69  $response = $this->doRemoteCall($request, false);
70  return $response;
71  }
72 
73  /**
74  * Do a remote call.
75  * @param $request The Request instance
76  * @param $isLogin Boolean whether this request is a login request or not
77  * @return The Response instance
78  */
79  protected function doRemoteCall(Request $request, $isLogin) {
80  // initially login, if no cookie is set
81  $cookyJar = $this->client->getCookieJar();
82  if (!$isLogin && sizeof($cookyJar->getAllCookies()) == 0) {
83  $response = $this->doLogin();
84  }
85 
86  // do the request
87  $request->setResponseFormat('json');
88  $this->client->resetParameters();
89  $this->client->setParameterPost('controller', $request->getSender());
90  $this->client->setParameterPost('context', $request->getContext());
91  $this->client->setParameterPost('action', $request->getAction());
92  $this->client->setParameterPost('request_format', $request->getFormat());
93  $this->client->setParameterPost('response_format', $request->getResponseFormat());
94  $this->client->setParameterPost($request->getValues());
95  try {
96  $httpResponse = $this->client->request();
97  }
98  catch (\Exception $ex) {
99  self::$logger->error("Error in remote call to ".$url.":\n".$ex, __FILE__);
100  throw new \RuntimeException("Error in remote call to ".$url.": ".$ex->getMessage());
101  }
102 
103  // deserialize the response
104  $responseData = json_decode($httpResponse->getBody(), true);
105  $response = new ControllerMessage('', '', '', $responseData);
106  $response->setFormat('json');
107  $formatter = ObjectFactory::getInstance('formatter');
108  $formatter->deserialize($response);
109 
110  // handle errors
111  if (!$response->getValue('success'))
112  {
113  $errorMsg = $response->getValue('errorMsg');
114  // if the session expired, try to relogin
115  if (strpos('Authorization failed', $errorMsg) === 0 && !$isLogin) {
116  $this->doLogin();
117  }
118  $url = $this->client->getUri();
119  self::$logger->error("Error in remote call to ".$url.": ".$errorMsg."\n".$response->toString(), __FILE__);
120  throw new \RuntimeException("Error in remote call: $errorMsg");
121  }
122  return $response;
123  }
124 
125  /**
126  * Do the login request. If the request is successful,
127  * the session id will be set.
128  * @return True on success
129  */
130  protected function doLogin() {
131  if ($this->user) {
132  $request = ObjectFactory::getNewInstance('request');
133  $request->setAction('login');
134  $request->setValues([
135  'login' => $this->user['login'],
136  'password' => $this->user['password']
137  ]);
138  $response = $this->doRemoteCall($request, true);
139  if ($response->getValue('success')) {
140  $this->sessionId = $response->getValue('sid');
141  return true;
142  }
143  }
144  else {
145  throw new \RuntimeException("Remote user required for remote call.");
146  }
147  }
148 
149  /**
150  * Error handling method
151  * @param $response The Response instance
152  */
153  protected function handleError($response) {
154  $errorMsg = $response->getValue('errorMsg');
155  self::$logger->error("Error in remote call to ".$this->serverUrl.": ".$errorMsg."\n".$response->toString(), __FILE__);
156  throw new \RuntimeException("Error in remote call to ".$this->serverUrl.": ".$errorMsg);
157  }
158 }
159 ?>
__construct($serverUrl, $user)
Constructor.
Definition: HTTPClient.php:49
Request holds the request values that are used as input to Controller instances.
Definition: Request.php:18
handleError($response)
Error handling method.
Definition: HTTPClient.php:153
getSender()
Get the name of the sending Controller.
doLogin()
Do the login request.
Definition: HTTPClient.php:130
getValues()
Get all key value pairs.
getContext()
Get the name of the context.
getFormat()
Get the message format.
getResponseFormat()
Get the message response format.
getAction()
Get the name of the action.
ConfigurationException signals an exception in the configuration.
call(Request $request)
Do a call to the remote server.
Definition: HTTPClient.php:68
RemotingClient defines the interface for clients to be used with RemotingServer.
static getLogger($name)
Get the logger with the given name.
Definition: LogManager.php:37
Messages are sent between Controllers and are used to transfer data between them.
static getNewInstance($name, $dynamicConfiguration=[])
static getInstance($name, $dynamicConfiguration=[])
setResponseFormat($format)
Set the desired response format.
LogManager is used to retrieve Logger instances.
Definition: LogManager.php:20
doRemoteCall(Request $request, $isLogin)
Do a remote call.
Definition: HTTPClient.php:79
ObjectFactory implements the service locator pattern by wrapping a Factory instance and providing sta...
HTTPClient is used to do calls to other wCMF instances over HTTP.
Definition: HTTPClient.php:35