|  | @@ -1,7 +1,9 @@
 | 
	
		
			
				|  |  |  import urllib.parse
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +import httpx
 | 
	
		
			
				|  |  |  from flask_restful import marshal_with, reqparse
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +import services
 | 
	
		
			
				|  |  |  from controllers.common import helpers
 | 
	
		
			
				|  |  |  from controllers.web.wraps import WebApiResource
 | 
	
		
			
				|  |  |  from core.file import helpers as file_helpers
 | 
	
	
		
			
				|  | @@ -9,19 +11,22 @@ from core.helper import ssrf_proxy
 | 
	
		
			
				|  |  |  from fields.file_fields import file_fields_with_signed_url, remote_file_info_fields
 | 
	
		
			
				|  |  |  from services.file_service import FileService
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +from .error import FileTooLargeError, UnsupportedFileTypeError
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  class RemoteFileInfoApi(WebApiResource):
 | 
	
		
			
				|  |  |      @marshal_with(remote_file_info_fields)
 | 
	
		
			
				|  |  |      def get(self, app_model, end_user, url):
 | 
	
		
			
				|  |  |          decoded_url = urllib.parse.unquote(url)
 | 
	
		
			
				|  |  | -        try:
 | 
	
		
			
				|  |  | -            response = ssrf_proxy.head(decoded_url)
 | 
	
		
			
				|  |  | -            return {
 | 
	
		
			
				|  |  | -                "file_type": response.headers.get("Content-Type", "application/octet-stream"),
 | 
	
		
			
				|  |  | -                "file_length": int(response.headers.get("Content-Length", -1)),
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -        except Exception as e:
 | 
	
		
			
				|  |  | -            return {"error": str(e)}, 400
 | 
	
		
			
				|  |  | +        resp = ssrf_proxy.head(decoded_url)
 | 
	
		
			
				|  |  | +        if resp.status_code != httpx.codes.OK:
 | 
	
		
			
				|  |  | +            # failed back to get method
 | 
	
		
			
				|  |  | +            resp = ssrf_proxy.get(decoded_url, timeout=3)
 | 
	
		
			
				|  |  | +        resp.raise_for_status()
 | 
	
		
			
				|  |  | +        return {
 | 
	
		
			
				|  |  | +            "file_type": resp.headers.get("Content-Type", "application/octet-stream"),
 | 
	
		
			
				|  |  | +            "file_length": int(resp.headers.get("Content-Length", -1)),
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  class RemoteFileUploadApi(WebApiResource):
 | 
	
	
		
			
				|  | @@ -33,28 +38,30 @@ class RemoteFileUploadApi(WebApiResource):
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          url = args["url"]
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        response = ssrf_proxy.head(url)
 | 
	
		
			
				|  |  | -        response.raise_for_status()
 | 
	
		
			
				|  |  | +        resp = ssrf_proxy.head(url=url)
 | 
	
		
			
				|  |  | +        if resp.status_code != httpx.codes.OK:
 | 
	
		
			
				|  |  | +            resp = ssrf_proxy.get(url=url, timeout=3)
 | 
	
		
			
				|  |  | +        resp.raise_for_status()
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        file_info = helpers.guess_file_info_from_response(response)
 | 
	
		
			
				|  |  | +        file_info = helpers.guess_file_info_from_response(resp)
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          if not FileService.is_file_size_within_limit(extension=file_info.extension, file_size=file_info.size):
 | 
	
		
			
				|  |  | -            return {"error": "File size exceeded"}, 400
 | 
	
		
			
				|  |  | +            raise FileTooLargeError
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        response = ssrf_proxy.get(url)
 | 
	
		
			
				|  |  | -        response.raise_for_status()
 | 
	
		
			
				|  |  | -        content = response.content
 | 
	
		
			
				|  |  | +        content = resp.content if resp.request.method == "GET" else ssrf_proxy.get(url).content
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          try:
 | 
	
		
			
				|  |  |              upload_file = FileService.upload_file(
 | 
	
		
			
				|  |  |                  filename=file_info.filename,
 | 
	
		
			
				|  |  |                  content=content,
 | 
	
		
			
				|  |  |                  mimetype=file_info.mimetype,
 | 
	
		
			
				|  |  | -                user=end_user,  # Use end_user instead of current_user
 | 
	
		
			
				|  |  | +                user=end_user,
 | 
	
		
			
				|  |  |                  source_url=url,
 | 
	
		
			
				|  |  |              )
 | 
	
		
			
				|  |  | -        except Exception as e:
 | 
	
		
			
				|  |  | -            return {"error": str(e)}, 400
 | 
	
		
			
				|  |  | +        except services.errors.file.FileTooLargeError as file_too_large_error:
 | 
	
		
			
				|  |  | +            raise FileTooLargeError(file_too_large_error.description)
 | 
	
		
			
				|  |  | +        except services.errors.file.UnsupportedFileTypeError:
 | 
	
		
			
				|  |  | +            raise UnsupportedFileTypeError
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          return {
 | 
	
		
			
				|  |  |              "id": upload_file.id,
 |