2 # ============LICENSE_START===============================================
3 # Copyright (C) 2020 Nordix Foundation. All rights reserved.
4 # ========================================================================
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
9 # http://www.apache.org/licenses/LICENSE-2.0
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
16 # ============LICENSE_END=================================================
19 from flask import Flask, request, Response
20 from time import sleep
22 from datetime import datetime
28 # Disable all logging of GET on reading counters and db
29 class AjaxFilter(logging.Filter):
30 def filter(self, record):
31 return ("/counter/" not in record.getMessage()) and ("/db" not in record.getMessage())
33 log = logging.getLogger('werkzeug')
34 log.addFilter(AjaxFilter())
38 # list of callback messages
50 # Request and response constants
51 CALLBACK_URL="/callbacks/<string:id>"
52 APP_READ_URL="/get-event/<string:id>"
53 APP_READ_ALL_URL="/get-all-events/<string:id>"
56 MIME_TEXT="text/plain"
57 MIME_JSON="application/json"
58 CAUGHT_EXCEPTION="Caught exception: "
59 SERVER_ERROR="Server error :"
60 TIME_STAMP="cr-timestamp"
62 # Remote host lookup and print host name
63 def remote_host_logging(request):
65 if request.environ.get('HTTP_X_FORWARDED_FOR') is None:
66 host_ip=str(request.environ['REMOTE_ADDR'])
68 host_ip=str(request.environ['HTTP_X_FORWARDED_FOR'])
70 if (host_ip.startswith('::ffff:')):
71 host_ip=host_ip[len(prefix):]
73 name, alias, addresslist = socket.gethostbyaddr(host_ip)
74 print("Calling host: "+str(name))
76 print("Calling host not possible to retrieve IP: "+str(host_ip))
85 ### Callback interface, for control
87 # Fetch the oldest callback message for an id
88 # URI and parameter, (GET): /get-event/<id>
89 # response: message + 200 or just 204 or just 500(error)
90 @app.route(APP_READ_URL,
92 def receiveresponse(id):
94 global cntr_msg_fetched
97 if ((id in msg_callbacks.keys()) and (len(msg_callbacks[id]) > 0)):
99 cntr_callbacks[id][1]+=1
100 msg=msg_callbacks[id][0]
101 print("Fetching msg for id: "+id+", msg="+str(msg))
103 del msg_callbacks[id][0]
104 return json.dumps(msg),200
105 print("No messages for id: "+id)
106 except Exception as e:
107 print(CAUGHT_EXCEPTION+str(e))
108 traceback.print_exc()
113 # Fetch all callback message for an id in an array
114 # URI and parameter, (GET): /get-all-events/<id>
115 # response: message + 200 or just 500(error)
116 @app.route(APP_READ_ALL_URL,
118 def receiveresponse_all(id):
120 global cntr_msg_fetched
123 if ((id in msg_callbacks.keys()) and (len(msg_callbacks[id]) > 0)):
124 cntr_msg_fetched+=len(msg_callbacks[id])
125 cntr_callbacks[id][1]+=len(msg_callbacks[id])
126 msg=msg_callbacks[id]
127 print("Fetching all msgs for id: "+id+", msg="+str(msg))
129 del sub_msg[TIME_STAMP]
130 del msg_callbacks[id]
131 return json.dumps(msg),200
132 print("No messages for id: "+id)
133 except Exception as e:
134 print(CAUGHT_EXCEPTION+str(e))
135 traceback.print_exc()
139 return json.dumps(msg),200
141 # Receive a callback message
142 # URI and payload, (PUT or POST): /callbacks/<id> <json messages>
143 # response: OK 200 or 500 for other errors
144 @app.route(CALLBACK_URL,
145 methods=['PUT','POST'])
146 def events_write(id):
148 global cntr_msg_callbacks
151 print("Received callback for id: "+id +", content-type="+request.content_type)
152 remote_host_logging(request)
154 if (request.content_type == MIME_JSON):
156 msg = json.loads(data)
157 print("Payload(json): "+str(msg))
160 print("Payload(content-type="+request.content_type+"). Setting empty json as payload")
161 except Exception as e:
163 print("(Exception) Payload does not contain any json, setting empty json as payload")
164 traceback.print_exc()
166 cntr_msg_callbacks += 1
167 msg[TIME_STAMP]=str(datetime.now())
168 if (id in msg_callbacks.keys()):
169 msg_callbacks[id].append(msg)
172 msg_callbacks[id].append(msg)
174 if (id in cntr_callbacks.keys()):
175 cntr_callbacks[id][0] += 1
177 cntr_callbacks[id]=[]
178 cntr_callbacks[id].append(1)
179 cntr_callbacks[id].append(0)
181 except Exception as e:
182 print(CAUGHT_EXCEPTION+str(e))
183 traceback.print_exc()
188 ### Functions for test ###
190 # Dump the whole db of current callbacks
191 # URI and parameter, (GET): /db
192 # response: message + 200
193 @app.route(DUMP_ALL_URL,
196 return json.dumps(msg_callbacks),200
198 ### Functions for metrics read out ###
200 @app.route('/counter/received_callbacks',
202 def requests_submitted():
203 req_id = request.args.get('id')
205 return Response(str(cntr_msg_callbacks), status=200, mimetype=MIME_TEXT)
207 if (req_id in cntr_callbacks.keys()):
208 return Response(str(cntr_callbacks[req_id][0]), status=200, mimetype=MIME_TEXT)
210 return Response(str("0"), status=200, mimetype=MIME_TEXT)
212 @app.route('/counter/fetched_callbacks',
214 def requests_fetched():
215 req_id = request.args.get('id')
217 return Response(str(cntr_msg_fetched), status=200, mimetype=MIME_TEXT)
219 if (req_id in cntr_callbacks.keys()):
220 return Response(str(cntr_callbacks[req_id][1]), status=200, mimetype=MIME_TEXT)
222 return Response(str("0"), status=200, mimetype=MIME_TEXT)
224 @app.route('/counter/current_messages',
226 def current_messages():
227 req_id = request.args.get('id')
229 return Response(str(cntr_msg_callbacks-cntr_msg_fetched), status=200, mimetype=MIME_TEXT)
231 if (req_id in cntr_callbacks.keys()):
232 return Response(str(cntr_callbacks[req_id][0]-cntr_callbacks[req_id][1]), status=200, mimetype=MIME_TEXT)
234 return Response(str("0"), status=200, mimetype=MIME_TEXT)
239 # Reset all messsages and counters
241 methods=['GET', 'POST', 'PUT'])
244 global cntr_msg_fetched
245 global cntr_msg_callbacks
246 global cntr_callbacks
253 return Response('OK', status=200, mimetype=MIME_TEXT)
255 ### Main function ###
257 if __name__ == "__main__":
258 app.run(port=HOST_PORT, host=HOST_IP)