Remove ECOMP in headers
[clamp.git] / src / test / resources / http-cache / third_party_proxy.py
1 #!/usr/bin/env python2
2 ###
3 # ============LICENSE_START=======================================================
4 # ONAP CLAMP
5 # ================================================================================
6 # Copyright (C) 2018 AT&T Intellectual Property. All rights
7 #                             reserved.
8 # ================================================================================
9 # Licensed under the Apache License, Version 2.0 (the "License");
10 # you may not use this file except in compliance with the License.
11 # You may obtain a copy of the License at
12 #
13 # http://www.apache.org/licenses/LICENSE-2.0
14 #
15 # Unless required by applicable law or agreed to in writing, software
16 # distributed under the License is distributed on an "AS IS" BASIS,
17 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 # See the License for the specific language governing permissions and
19 # limitations under the License.
20 # ============LICENSE_END============================================
21 # ===================================================================
22 #
23 ###
24
25 import json
26 import requests
27 import os
28 import sys
29 import SimpleHTTPServer
30 import SocketServer
31 import argparse
32 import tempfile
33 import signal
34 import uuid
35 import shutil
36
37 parser = argparse.ArgumentParser(description="3rd party Cache & Replay")
38 parser.add_argument("--username", "-u", type=str, help="Set the username for contacting 3rd party - only used for GET")
39 parser.add_argument("--password", "-p", type=str, help="Set the password for contacting 3rd party - only used for GET")
40 parser.add_argument("--root",     "-r", default=tempfile.mkdtemp, type=str, help="Root folder for the proxy cache")
41 parser.add_argument("--proxy"         , type=str, help="Url of the  Act as a proxy. If not set, this script only uses the cache and will return a 404 if files aren't found")
42 parser.add_argument("--port",     "-P", type=int, default="8081", help="Port on which the proxy should listen to")
43 parser.add_argument("--verbose",  "-v", type=bool, help="Print more information in case of error")
44 parser.add_argument("--proxyaddress","-a", type=str, help="Address of this proxy, generally either third_party_proxy:8085 or localhost:8085 depending if started with docker-compose or not")
45 options = parser.parse_args()
46
47
48 PORT = options.port
49 HOST = options.proxy
50 AUTH = (options.username, options.password)
51 HEADERS = {'X-ECOMP-InstanceID':'CLAMP'}
52 CACHE_ROOT = options.root
53 PROXY_ADDRESS=options.proxyaddress
54
55 def signal_handler(signal_sent, frame):
56     global httpd
57     if signal_sent == signal.SIGINT:
58         print('Got Ctrl-C (SIGINT)')
59         httpd.socket.close()
60         httpd.shutdown()
61         httpd.server_close()
62
63 class Proxy(SimpleHTTPServer.SimpleHTTPRequestHandler):
64
65     def print_headers(self):
66         for header,value in self.headers.items():
67             print("header: %s : %s" % (header, value))
68
69     def check_credentials(self):
70         pass
71
72     def _send_content(self, header_file, content_file):
73         self.send_response(200)
74         with open(header_file, 'rb') as f:
75             headers = json.load(f)
76             for key,value in headers.items():
77                 if key in ('Transfer-Encoding',):
78                     continue
79                 self.send_header(key, value)
80             self.end_headers()
81         with open(content_file,'rb') as f:
82             fc = f.read()
83             self.wfile.write(fc)
84
85     def _write_cache(self,cached_file, header_file, content_file, response):
86         os.makedirs(cached_file, True)
87         with open(content_file, 'w') as f:
88             f.write(response.raw.read())
89         with open(header_file, 'w') as f:
90             json.dump(dict(response.raw.headers), f)
91     # Entry point of the code
92     def do_GET(self):
93         print("\n\n\nGot a GET request for %s " % self.path)
94
95         self.print_headers()
96         self.check_credentials()
97
98         cached_file = '%s/%s' % (CACHE_ROOT, self.path,)
99         print("Cached file name before escaping : %s" % cached_file)
100         cached_file = cached_file.replace('<','&#60;').replace('>','&#62;').replace('?','&#63;').replace('*','&#42;').replace('\\','&#42;').replace(':','&#58;').replace('|','&#124;')
101         print("Cached file name after escaping (used for cache storage) : %s" % cached_file)
102         cached_file_content = "%s/.file" % (cached_file,)
103         cached_file_header = "%s/.header" % (cached_file,)
104
105         _file_available = os.path.exists(cached_file_content)
106
107         if not _file_available:
108             print("Request for data currently not present in cache: %s" % (cached_file,))
109
110             if self.path.startswith("/dcae-service-types?asdcResourceId="):
111                 print "self.path start with /dcae-service-types?asdcResourceId=, generating response json..."
112                 uuidGenerated = str(uuid.uuid4())
113                 typeId = "typeId-" + uuidGenerated
114                 typeName = "typeName-" + uuidGenerated
115                 print "typeId generated: " + typeName + " and typeName: "+ typeId
116                 jsonGenerated = "{\"totalCount\":1, \"items\":[{\"typeId\":\"" + typeId + "\", \"typeName\":\"" + typeName +"\"}]}"
117                 print "jsonGenerated: " + jsonGenerated
118
119                 os.makedirs(cached_file, True)
120                 with open(cached_file_header, 'w') as f:
121                     f.write("{\"Content-Length\": \"" + str(len(jsonGenerated)) + "\", \"Content-Type\": \"application/json\"}")
122                 with open(cached_file_content, 'w') as f:
123                     f.write(jsonGenerated)
124             elif self.path.startswith("/dcae-operationstatus"):
125                 print "self.path start with /dcae-operationstatus, generating response json..."
126                 jsonGenerated =  "{\"operationType\": \"operationType1\", \"status\": \"succeeded\"}"
127                 print "jsonGenerated: " + jsonGenerated
128
129                 os.makedirs(cached_file, True)
130                 with open(cached_file_header, 'w') as f:
131                     f.write("{\"Content-Length\": \"" + str(len(jsonGenerated)) + "\", \"Content-Type\": \"application/json\"}")
132                 with open(cached_file_content, 'w') as f:
133                     f.write(jsonGenerated)
134             else:
135                 if not HOST:
136                     self.send_response(404)
137                     return "404 Not found"
138
139                 url = '%s%s' % (HOST, self.path)
140                 response = requests.get(url, auth=AUTH, headers=HEADERS, stream=True)
141
142                 if response.status_code == 200:
143                     self._write_cache(cached_file, cached_file_header, cached_file_content, response)
144                 else:
145                     print('Error when requesting file :')
146                     print('Requested url : %s' % (url,))
147                     print('Status code : %s' % (response.status_code,))
148                     print('Content : %s' % (response.content,))
149                     self.send_response(response.status_code)
150                     return response.content
151         else:
152             print("Request for data currently present in cache: %s" % (cached_file,))
153
154         self._send_content(cached_file_header, cached_file_content)
155
156         if self.path.startswith("/dcae-service-types?asdcResourceId="):
157             print "DCAE case deleting folder created " + cached_file
158             shutil.rmtree(cached_file, ignore_errors=False, onerror=None)
159         else:
160             print "NOT in DCAE case deleting folder created " + cached_file
161
162     def do_POST(self):
163         print("\n\n\nGot a POST for %s" % self.path)
164         self.check_credentials()
165         self.data_string = self.rfile.read(int(self.headers['Content-Length']))
166         print("data-string:\n %s" % self.data_string)
167         print("self.headers:\n %s" % self.headers)
168
169         cached_file = '%s/%s' % (CACHE_ROOT, self.path,)
170         print("Cached file name before escaping : %s" % cached_file)
171         cached_file = cached_file.replace('<','&#60;').replace('>','&#62;').replace('?','&#63;').replace('*','&#42;').replace('\\','&#42;').replace(':','&#58;').replace('|','&#124;')
172         print("Cached file name after escaping (used for cache storage) : %s" % cached_file)
173         cached_file_content = "%s/.file" % (cached_file,)
174         cached_file_header = "%s/.header" % (cached_file,)
175
176         _file_available = os.path.exists(cached_file_content)
177
178         if not _file_available:
179             if self.path.startswith("/sdc/v1/catalog/services/"):
180                 print "self.path start with /sdc/v1/catalog/services/, generating response json..."
181                 jsondata = json.loads(self.data_string)
182                 jsonGenerated = "{\"artifactName\":\"" + jsondata['artifactName'] + "\",\"artifactType\":\"" + jsondata['artifactType'] + "\",\"artifactURL\":\"" + self.path + "\",\"artifactDescription\":\"" + jsondata['description'] + "\",\"artifactChecksum\":\"ZjJlMjVmMWE2M2M1OTM2MDZlODlmNTVmZmYzNjViYzM=\",\"artifactUUID\":\"" + str(uuid.uuid4()) + "\",\"artifactVersion\":\"1\"}"
183                 print "jsonGenerated: " + jsonGenerated
184
185                 os.makedirs(cached_file, True)
186                 with open(cached_file_header, 'w') as f:
187                     f.write("{\"Content-Length\": \"" + str(len(jsonGenerated)) + "\", \"Content-Type\": \"application/json\"}")
188                 with open(cached_file_content, 'w') as f:
189                     f.write(jsonGenerated)
190             else:
191                 if not HOST:
192                     self.send_response(404)
193                     return "404 Not found"
194
195                 print("Request for data currently not present in cache: %s" % (cached_file,))
196
197                 url = '%s%s' % (HOST, self.path)
198                 print("url: %s" % (url,))
199                 response = requests.post(url, data=self.data_string, headers=self.headers, stream=True)
200
201                 if response.status_code == 200:
202                     self._write_cache(cached_file, cached_file_header, cached_file_content, response)
203                 else:
204                     print('Error when requesting file :')
205                     print('Requested url : %s' % (url,))
206                     print('Status code : %s' % (response.status_code,))
207                     print('Content : %s' % (response.content,))
208                     self.send_response(response.status_code)
209                     return response.content
210         else:
211             print("Request for data present in cache: %s" % (cached_file,))
212
213         self._send_content(cached_file_header, cached_file_content)
214
215     def do_PUT(self):
216         print("\n\n\nGot a PUT for %s " % self.path)
217         self.check_credentials()
218         self.data_string = self.rfile.read(int(self.headers['Content-Length']))
219         print("data-string:\n %s" % self.data_string)
220         print("self.headers:\n %s" % self.headers)
221
222         cached_file = '%s/%s' % (CACHE_ROOT, self.path,)
223         print("Cached file name before escaping : %s" % cached_file)
224         cached_file = cached_file.replace('<','&#60;').replace('>','&#62;').replace('?','&#63;').replace('*','&#42;').replace('\\','&#42;').replace(':','&#58;').replace('|','&#124;')
225         print("Cached file name after escaping (used for cache storage) : %s" % cached_file)
226         cached_file_content = "%s/.file" % (cached_file,)
227         cached_file_header = "%s/.header" % (cached_file,)
228
229         _file_available = os.path.exists(cached_file_content)
230
231         if not _file_available:
232             if self.path.startswith("/dcae-deployments/"):
233                 print "self.path start with /dcae-deployments/, generating response json..."
234                 #jsondata = json.loads(self.data_string)
235                 jsonGenerated = "{\"links\":{\"status\":\"http:\/\/" + PROXY_ADDRESS + "\/dcae-operationstatus\",\"test2\":\"test2\"}}"
236                 print "jsonGenerated: " + jsonGenerated
237
238                 os.makedirs(cached_file, True)
239                 with open(cached_file_header, 'w') as f:
240                     f.write("{\"Content-Length\": \"" + str(len(jsonGenerated)) + "\", \"Content-Type\": \"application/json\"}")
241                 with open(cached_file_content, 'w') as f:
242                     f.write(jsonGenerated)
243             else:
244                 if not HOST:
245                     self.send_response(404)
246                     return "404 Not found"
247
248                 print("Request for data currently not present in cache: %s" % (cached_file,))
249
250                 url = '%s%s' % (HOST, self.path)
251                 print("url: %s" % (url,))
252                 response = requests.put(url, data=self.data_string, headers=self.headers, stream=True)
253
254                 if response.status_code == 200:
255                     self._write_cache(cached_file, cached_file_header, cached_file_content, response)
256                 else:
257                     print('Error when requesting file :')
258                     print('Requested url : %s' % (url,))
259                     print('Status code : %s' % (response.status_code,))
260                     print('Content : %s' % (response.content,))
261                     self.send_response(response.status_code)
262                     return response.content
263         else:
264             print("Request for data present in cache: %s" % (cached_file,))
265
266         self._send_content(cached_file_header, cached_file_content)
267
268
269     def do_DELETE(self):
270         print("\n\n\nGot a DELETE for %s " % self.path)
271         self.check_credentials()
272         print("self.headers:\n %s" % self.headers)
273
274         cached_file = '%s/%s' % (CACHE_ROOT, self.path,)
275         print("Cached file name before escaping : %s" % cached_file)
276         cached_file = cached_file.replace('<','&#60;').replace('>','&#62;').replace('?','&#63;').replace('*','&#42;').replace('\\','&#42;').replace(':','&#58;').replace('|','&#124;')
277         print("Cached file name after escaping (used for cache storage) : %s" % cached_file)
278         cached_file_content = "%s/.file" % (cached_file,)
279         cached_file_header = "%s/.header" % (cached_file,)
280
281         _file_available = os.path.exists(cached_file_content)
282
283         if not _file_available:
284             if self.path.startswith("/dcae-deployments/"):
285                 print "self.path start with /dcae-deployments/, generating response json..."
286                 #jsondata = json.loads(self.data_string)
287                 jsonGenerated = "{\"links\":{\"status\":\"http:\/\/" + PROXY_ADDRESS + "\/dcae-operationstatus\",\"test2\":\"test2\"}}"
288                 print "jsonGenerated: " + jsonGenerated
289
290                 os.makedirs(cached_file, True)
291                 with open(cached_file_header, 'w') as f:
292                     f.write("{\"Content-Length\": \"" + str(len(jsonGenerated)) + "\", \"Content-Type\": \"application/json\"}")
293                 with open(cached_file_content, 'w') as f:
294                     f.write(jsonGenerated)
295             else:
296                 if not HOST:
297                     self.send_response(404)
298                     return "404 Not found"
299
300                 print("Request for data currently not present in cache: %s" % (cached_file,))
301
302                 url = '%s%s' % (HOST, self.path)
303                 print("url: %s" % (url,))
304                 response = requests.put(url, data=self.data_string, headers=self.headers, stream=True)
305
306                 if response.status_code == 200:
307                     self._write_cache(cached_file, cached_file_header, cached_file_content, response)
308                 else:
309                     print('Error when requesting file :')
310                     print('Requested url : %s' % (url,))
311                     print('Status code : %s' % (response.status_code,))
312                     print('Content : %s' % (response.content,))
313                     self.send_response(response.status_code)
314                     return response.content
315         else:
316             print("Request for data present in cache: %s" % (cached_file,))
317
318         self._send_content(cached_file_header, cached_file_content)
319
320
321
322 # Main code that start the HTTP server
323 httpd = SocketServer.ForkingTCPServer(('', PORT), Proxy)
324 httpd.allow_reuse_address = True
325 print "Listening on port "+ str(PORT) + " and caching in " + CACHE_ROOT + "(Press Ctrl+C to stop HTTPD Caching script)"
326 signal.signal(signal.SIGINT, signal_handler)
327 httpd.serve_forever()