Spaces:
Sleeping
Sleeping
| import os | |
| import json | |
| import time | |
| import requests | |
| import urllib3 | |
| import base64 | |
| from flask import Flask, render_template, request, jsonify | |
| # Suppress InsecureRequestWarning for verify=False | |
| urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) | |
| app = Flask(__name__) | |
| app.secret_key = os.urandom(24) | |
| app.config['MAX_CONTENT_LENGTH'] = 32 * 1024 * 1024 # 32MB limit | |
| # Standard Jinja2 delimiters are used. | |
| # Vue.js will be configured to use ['${', '}'] to avoid conflict. | |
| def index(): | |
| return render_template('index.html') | |
| def proxy_request(): | |
| try: | |
| data = request.json | |
| if not data: | |
| return jsonify({'error': 'No data provided'}), 400 | |
| method = data.get('method', 'GET').upper() | |
| url = data.get('url') | |
| headers = data.get('headers', {}) | |
| body = data.get('body', None) | |
| params = data.get('params', {}) | |
| if not url: | |
| return jsonify({'error': 'URL is required'}), 400 | |
| # Ensure headers is a dict | |
| if not isinstance(headers, dict): | |
| headers = {} | |
| start_time = time.time() | |
| # Prepare arguments | |
| kwargs = { | |
| 'method': method, | |
| 'url': url, | |
| 'headers': headers, | |
| 'params': params, | |
| 'timeout': 60, # Increased timeout | |
| 'verify': False, # Allow testing local/self-signed endpoints | |
| 'allow_redirects': True | |
| } | |
| # Handle Body | |
| if body: | |
| content_type = '' | |
| # Case insensitive search for Content-Type | |
| for k, v in headers.items(): | |
| if k.lower() == 'content-type': | |
| content_type = v.lower() | |
| break | |
| if 'application/json' in content_type: | |
| if isinstance(body, str): | |
| try: | |
| # Try to parse to ensure it's valid JSON if we want to send as json kwarg | |
| json_body = json.loads(body) | |
| kwargs['json'] = json_body | |
| except: | |
| # Send as raw string if it fails to parse | |
| kwargs['data'] = body | |
| else: | |
| kwargs['json'] = body | |
| else: | |
| # x-www-form-urlencoded or plain text | |
| kwargs['data'] = body.encode('utf-8') if isinstance(body, str) else body | |
| resp = requests.request(**kwargs) | |
| duration = (time.time() - start_time) * 1000 # ms | |
| # Format response headers | |
| resp_headers = dict(resp.headers) | |
| resp_content_type = resp_headers.get('Content-Type', '').lower() | |
| # Determine how to return data | |
| is_binary = False | |
| is_json = False | |
| resp_data = None | |
| # Check for binary content types (images, pdfs, audio, etc.) | |
| binary_types = ['image/', 'audio/', 'video/', 'application/pdf', 'application/octet-stream', 'application/zip'] | |
| if any(bt in resp_content_type for bt in binary_types): | |
| is_binary = True | |
| resp_data = base64.b64encode(resp.content).decode('utf-8') | |
| else: | |
| # Try to parse response body as JSON | |
| try: | |
| resp_data = resp.json() | |
| is_json = True | |
| except: | |
| # Fallback to text | |
| resp_data = resp.text | |
| return jsonify({ | |
| 'status': resp.status_code, | |
| 'status_text': resp.reason, | |
| 'headers': resp_headers, | |
| 'data': resp_data, | |
| 'is_json': is_json, | |
| 'is_binary': is_binary, | |
| 'content_type': resp_headers.get('Content-Type', ''), | |
| 'duration': round(duration, 2), | |
| 'size': len(resp.content) | |
| }) | |
| except requests.exceptions.RequestException as e: | |
| return jsonify({ | |
| 'error': str(e), | |
| 'duration': round((time.time() - (start_time if 'start_time' in locals() else time.time())) * 1000, 2) | |
| }), 500 | |
| except Exception as e: | |
| return jsonify({ | |
| 'error': f"Internal Server Error: {str(e)}", | |
| 'duration': 0 | |
| }), 500 | |
| if __name__ == '__main__': | |
| port = int(os.environ.get('PORT', 7860)) | |
| app.run(host='0.0.0.0', port=port, debug=True) | |