mirror of
				https://github.com/ivanch/tcc.git
				synced 2025-11-04 03:07:36 +00:00 
			
		
		
		
	Compare commits
	
		
			3 Commits
		
	
	
		
			05dad7ade5
			...
			FlaskAPI
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					8d9c1598a2 | ||
| 
						 | 
					84df834b82 | ||
| 
						 | 
					74a1a8458e | 
							
								
								
									
										10
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										10
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -1,14 +1,4 @@
 | 
				
			|||||||
.vs
 | 
					.vs
 | 
				
			||||||
__pycache__
 | 
					 | 
				
			||||||
bin
 | 
					bin
 | 
				
			||||||
obj
 | 
					obj
 | 
				
			||||||
*.vscode
 | 
					 | 
				
			||||||
__pycache__
 | 
					 | 
				
			||||||
.idea
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
*/target
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
*.png
 | 
					*.png
 | 
				
			||||||
*.csv
 | 
					 | 
				
			||||||
*.jpg
 | 
					 | 
				
			||||||
*.mp4
 | 
					 | 
				
			||||||
							
								
								
									
										8
									
								
								.idea/.gitignore
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								.idea/.gitignore
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,8 @@
 | 
				
			|||||||
 | 
					# Default ignored files
 | 
				
			||||||
 | 
					/shelf/
 | 
				
			||||||
 | 
					/workspace.xml
 | 
				
			||||||
 | 
					# Editor-based HTTP Client requests
 | 
				
			||||||
 | 
					/httpRequests/
 | 
				
			||||||
 | 
					# Datasource local storage ignored files
 | 
				
			||||||
 | 
					/dataSources/
 | 
				
			||||||
 | 
					/dataSources.local.xml
 | 
				
			||||||
							
								
								
									
										6
									
								
								.idea/inspectionProfiles/profiles_settings.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								.idea/inspectionProfiles/profiles_settings.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							@@ -0,0 +1,6 @@
 | 
				
			|||||||
 | 
					<component name="InspectionProjectProfileManager">
 | 
				
			||||||
 | 
					  <settings>
 | 
				
			||||||
 | 
					    <option name="USE_PROJECT_PROFILE" value="false" />
 | 
				
			||||||
 | 
					    <version value="1.0" />
 | 
				
			||||||
 | 
					  </settings>
 | 
				
			||||||
 | 
					</component>
 | 
				
			||||||
							
								
								
									
										4
									
								
								.idea/misc.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								.idea/misc.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							@@ -0,0 +1,4 @@
 | 
				
			|||||||
 | 
					<?xml version="1.0" encoding="UTF-8"?>
 | 
				
			||||||
 | 
					<project version="4">
 | 
				
			||||||
 | 
					  <component name="ProjectRootManager" version="2" project-jdk-name="Python 3.10" project-jdk-type="Python SDK" />
 | 
				
			||||||
 | 
					</project>
 | 
				
			||||||
							
								
								
									
										8
									
								
								.idea/modules.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								.idea/modules.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							@@ -0,0 +1,8 @@
 | 
				
			|||||||
 | 
					<?xml version="1.0" encoding="UTF-8"?>
 | 
				
			||||||
 | 
					<project version="4">
 | 
				
			||||||
 | 
					  <component name="ProjectModuleManager">
 | 
				
			||||||
 | 
					    <modules>
 | 
				
			||||||
 | 
					      <module fileurl="file://$PROJECT_DIR$/.idea/tcc.iml" filepath="$PROJECT_DIR$/.idea/tcc.iml" />
 | 
				
			||||||
 | 
					    </modules>
 | 
				
			||||||
 | 
					  </component>
 | 
				
			||||||
 | 
					</project>
 | 
				
			||||||
							
								
								
									
										8
									
								
								.idea/tcc.iml
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								.idea/tcc.iml
									
									
									
										generated
									
									
									
										Normal file
									
								
							@@ -0,0 +1,8 @@
 | 
				
			|||||||
 | 
					<?xml version="1.0" encoding="UTF-8"?>
 | 
				
			||||||
 | 
					<module type="PYTHON_MODULE" version="4">
 | 
				
			||||||
 | 
					  <component name="NewModuleRootManager">
 | 
				
			||||||
 | 
					    <content url="file://$MODULE_DIR$" />
 | 
				
			||||||
 | 
					    <orderEntry type="inheritedJdk" />
 | 
				
			||||||
 | 
					    <orderEntry type="sourceFolder" forTests="false" />
 | 
				
			||||||
 | 
					  </component>
 | 
				
			||||||
 | 
					</module>
 | 
				
			||||||
							
								
								
									
										6
									
								
								.idea/vcs.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								.idea/vcs.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							@@ -0,0 +1,6 @@
 | 
				
			|||||||
 | 
					<?xml version="1.0" encoding="UTF-8"?>
 | 
				
			||||||
 | 
					<project version="4">
 | 
				
			||||||
 | 
					  <component name="VcsDirectoryMappings">
 | 
				
			||||||
 | 
					    <mapping directory="" vcs="Git" />
 | 
				
			||||||
 | 
					  </component>
 | 
				
			||||||
 | 
					</project>
 | 
				
			||||||
@@ -23,7 +23,6 @@ namespace TCC.Controllers
 | 
				
			|||||||
            mstream.Position = 0;
 | 
					            mstream.Position = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            var result = ImageService.BoxBlurImage(mstream, radius);
 | 
					            var result = ImageService.BoxBlurImage(mstream, radius);
 | 
				
			||||||
            mstream.Close();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            var blurredImageStream = new MemoryStream();
 | 
					            var blurredImageStream = new MemoryStream();
 | 
				
			||||||
            result.Write(blurredImageStream);
 | 
					            result.Write(blurredImageStream);
 | 
				
			||||||
@@ -32,16 +31,28 @@ namespace TCC.Controllers
 | 
				
			|||||||
            return File(blurredImageStream, "image/png");
 | 
					            return File(blurredImageStream, "image/png");
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        [HttpGet("load-small-image")]
 | 
					        [HttpGet("load-image")]
 | 
				
			||||||
        public async Task<IActionResult> GetSimpleImage()
 | 
					        public async Task<IActionResult> GetSimpleImage()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            return File(ImageService.GetSimpleImage(), "image/png");
 | 
					            var result = ImageService.GetSimpleImage();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            var imageStream = new MemoryStream();
 | 
				
			||||||
 | 
					            result.Write(imageStream);
 | 
				
			||||||
 | 
					            imageStream.Position = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return File(imageStream, "image/png");
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        [HttpGet("load-big-image")]
 | 
					        [HttpGet("load-big-image")]
 | 
				
			||||||
        public async Task<IActionResult> GetBigImage()
 | 
					        public async Task<IActionResult> GetBigImage()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            return File(ImageService.GetBigImage(), "image/png");
 | 
					            var result = ImageService.GetBigImage();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            var imageStream = new MemoryStream();
 | 
				
			||||||
 | 
					            result.Write(imageStream);
 | 
				
			||||||
 | 
					            imageStream.Position = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return File(imageStream, "image/png");
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        [HttpPost("save-big-image")]
 | 
					        [HttpPost("save-big-image")]
 | 
				
			||||||
@@ -50,7 +61,6 @@ namespace TCC.Controllers
 | 
				
			|||||||
            MemoryStream mstream = new MemoryStream();
 | 
					            MemoryStream mstream = new MemoryStream();
 | 
				
			||||||
            await HttpContext.Request.Body.CopyToAsync(mstream);
 | 
					            await HttpContext.Request.Body.CopyToAsync(mstream);
 | 
				
			||||||
            mstream.Position = 0;
 | 
					            mstream.Position = 0;
 | 
				
			||||||
            mstream.Close();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            return Ok();
 | 
					            return Ok();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,7 +2,6 @@ FROM mcr.microsoft.com/dotnet/sdk:6.0-bullseye-slim AS build-env
 | 
				
			|||||||
WORKDIR /App
 | 
					WORKDIR /App
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Copy everything
 | 
					# Copy everything
 | 
				
			||||||
RUN apt update && apt install wget -y
 | 
					 | 
				
			||||||
COPY * .
 | 
					COPY * .
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Restore as distinct layers
 | 
					# Restore as distinct layers
 | 
				
			||||||
@@ -11,21 +10,15 @@ RUN dotnet restore
 | 
				
			|||||||
# Build a release
 | 
					# Build a release
 | 
				
			||||||
RUN dotnet build -c Release -o out
 | 
					RUN dotnet build -c Release -o out
 | 
				
			||||||
 | 
					
 | 
				
			||||||
RUN cd out && \
 | 
					 | 
				
			||||||
    wget https://files.ivanch.me/api/public/dl/iFuXSNhw/small-image.png && \
 | 
					 | 
				
			||||||
    wget https://files.ivanch.me/api/public/dl/81Bkht5C/big-image.png && \
 | 
					 | 
				
			||||||
    wget https://files.ivanch.me/api/public/dl/nAndfAjK/video.mp4 && \
 | 
					 | 
				
			||||||
    rm -rf runtimes && \
 | 
					 | 
				
			||||||
    mkdir -p ./static && \
 | 
					 | 
				
			||||||
    mv small-image.png ./static && \
 | 
					 | 
				
			||||||
    mv big-image.png ./static && \
 | 
					 | 
				
			||||||
    mv video.mp4 ./static
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Build runtime image
 | 
					# Build runtime image
 | 
				
			||||||
FROM mcr.microsoft.com/dotnet/aspnet:6.0-bullseye-slim
 | 
					FROM mcr.microsoft.com/dotnet/aspnet:6.0-bullseye-slim
 | 
				
			||||||
 | 
					
 | 
				
			||||||
WORKDIR /App
 | 
					WORKDIR /App
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					RUN wget https://files.ivanch.me/api/public/dl/QFCLgtrG/simpleimage.png && \
 | 
				
			||||||
 | 
					    wget https://files.ivanch.me/api/public/dl/E0VLgWbx/bigimage.png && \
 | 
				
			||||||
 | 
					    rm -rf runtimes
 | 
				
			||||||
 | 
					
 | 
				
			||||||
COPY --from=build-env /App/out .
 | 
					COPY --from=build-env /App/out .
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ENTRYPOINT ["dotnet", "/App/TCC.APP.dll"]
 | 
					ENTRYPOINT ["dotnet", "/App/TCC.APP.dll"]
 | 
				
			||||||
@@ -4,13 +4,13 @@ namespace tcc_app
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    public static class ImageHelper
 | 
					    public static class ImageHelper
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        public static byte[] SimpleImage;
 | 
					        public static MagickImage SimpleImage;
 | 
				
			||||||
        public static byte[] BigImage;
 | 
					        public static MagickImage BigImage;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        static ImageHelper()
 | 
					        static ImageHelper()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            SimpleImage = File.ReadAllBytes("static/small-image.png");
 | 
					            SimpleImage = new MagickImage("simpleimage.png");
 | 
				
			||||||
            BigImage = File.ReadAllBytes("static/big-image.png");
 | 
					            BigImage = new MagickImage("bigimage.png");
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,5 +1,4 @@
 | 
				
			|||||||
using Microsoft.AspNetCore.Server.Kestrel.Core;
 | 
					using Microsoft.AspNetCore.Server.Kestrel.Core;
 | 
				
			||||||
using Microsoft.Extensions.FileProviders;
 | 
					 | 
				
			||||||
using TCC.Services;
 | 
					using TCC.Services;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace TCC
 | 
					namespace TCC
 | 
				
			||||||
@@ -19,13 +18,9 @@ namespace TCC
 | 
				
			|||||||
                options.Limits.MaxRequestBodySize = int.MaxValue; // if don't set default value is: 30 MB
 | 
					                options.Limits.MaxRequestBodySize = int.MaxValue; // if don't set default value is: 30 MB
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            var app = builder.Build();
 | 
					            var app = builder.Build();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            app.UseStaticFiles(new StaticFileOptions
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                FileProvider = new PhysicalFileProvider(Path.Combine(builder.Environment.ContentRootPath, "static")),
 | 
					 | 
				
			||||||
                RequestPath = "/static"
 | 
					 | 
				
			||||||
            });
 | 
					 | 
				
			||||||
            app.MapControllers();
 | 
					            app.MapControllers();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            app.Run();
 | 
					            app.Run();
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -14,7 +14,7 @@
 | 
				
			|||||||
      "dotnetRunMessages": true,
 | 
					      "dotnetRunMessages": true,
 | 
				
			||||||
      "launchBrowser": false,
 | 
					      "launchBrowser": false,
 | 
				
			||||||
      "launchUrl": "weatherforecast",
 | 
					      "launchUrl": "weatherforecast",
 | 
				
			||||||
      "applicationUrl": "http://0.0.0.0:9090",
 | 
					      "applicationUrl": "http://0.0.0.0:5100",
 | 
				
			||||||
      "environmentVariables": {
 | 
					      "environmentVariables": {
 | 
				
			||||||
        "ASPNETCORE_ENVIRONMENT": "Development"
 | 
					        "ASPNETCORE_ENVIRONMENT": "Development"
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -62,16 +62,14 @@ namespace TCC.Services
 | 
				
			|||||||
            file.Close();
 | 
					            file.Close();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public byte[] GetSimpleImage()
 | 
					        public MagickImage GetSimpleImage()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            return File.ReadAllBytes("static/small-image.png");
 | 
					            return ImageHelper.SimpleImage;
 | 
				
			||||||
            //return ImageHelper.SimpleImage;
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public byte[] GetBigImage()
 | 
					        public MagickImage GetBigImage()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            return File.ReadAllBytes("static/big-image.png");
 | 
					            return ImageHelper.BigImage;
 | 
				
			||||||
            //return ImageHelper.BigImage;
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,33 +0,0 @@
 | 
				
			|||||||
<!DOCTYPE html>
 | 
					 | 
				
			||||||
<html>
 | 
					 | 
				
			||||||
<head>
 | 
					 | 
				
			||||||
    <title>Welcome to nginx!</title>
 | 
					 | 
				
			||||||
    <style>
 | 
					 | 
				
			||||||
        html {
 | 
					 | 
				
			||||||
            color-scheme: light dark;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        body {
 | 
					 | 
				
			||||||
            width: 35em;
 | 
					 | 
				
			||||||
            margin: 0 auto;
 | 
					 | 
				
			||||||
            font-family: Tahoma, Verdana, Arial, sans-serif;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    </style>
 | 
					 | 
				
			||||||
</head>
 | 
					 | 
				
			||||||
<body>
 | 
					 | 
				
			||||||
    <h1>Welcome to nginx!</h1>
 | 
					 | 
				
			||||||
    <p>
 | 
					 | 
				
			||||||
        If you see this page, the nginx web server is successfully installed and
 | 
					 | 
				
			||||||
        working. Further configuration is required.
 | 
					 | 
				
			||||||
    </p>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    <p>
 | 
					 | 
				
			||||||
        For online documentation and support please refer to
 | 
					 | 
				
			||||||
        <a href="http://nginx.org/">nginx.org</a>.<br />
 | 
					 | 
				
			||||||
        Commercial support is available at
 | 
					 | 
				
			||||||
        <a href="http://nginx.com/">nginx.com</a>.
 | 
					 | 
				
			||||||
    </p>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    <p><em>Thank you for using nginx.</em></p>
 | 
					 | 
				
			||||||
</body>
 | 
					 | 
				
			||||||
</html>
 | 
					 | 
				
			||||||
							
								
								
									
										1266
									
								
								ActixAPI/Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										1266
									
								
								ActixAPI/Cargo.lock
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -1,10 +0,0 @@
 | 
				
			|||||||
[package]
 | 
					 | 
				
			||||||
name = "ActixAPI"
 | 
					 | 
				
			||||||
version = "0.1.0"
 | 
					 | 
				
			||||||
edition = "2021"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[dependencies]
 | 
					 | 
				
			||||||
actix-web = "4"
 | 
					 | 
				
			||||||
actix-files = "0.6.2"
 | 
					 | 
				
			||||||
@@ -1,25 +0,0 @@
 | 
				
			|||||||
FROM rust:slim-bullseye AS build-env
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
WORKDIR /app
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
COPY . .
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
RUN apt update && apt install wget -y && \
 | 
					 | 
				
			||||||
    wget https://files.ivanch.me/api/public/dl/Dj0gkp-m/small-image.png && \
 | 
					 | 
				
			||||||
    wget https://files.ivanch.me/api/public/dl/FqHEPM1Q/big-image.png && \
 | 
					 | 
				
			||||||
    wget https://files.ivanch.me/api/public/dl/nTAYqZwD/video.mp4 && \
 | 
					 | 
				
			||||||
    mv small-image.png ./static && \
 | 
					 | 
				
			||||||
    mv big-image.png ./static && \
 | 
					 | 
				
			||||||
    mv video.mp4 ./static
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
RUN cargo build --release
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
FROM debian:bullseye-slim
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
WORKDIR /app
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
COPY --from=build-env /app/target/release .
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
COPY --from=build-env /app/static .
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
ENTRYPOINT ["./ActixAPI"]
 | 
					 | 
				
			||||||
@@ -1,40 +0,0 @@
 | 
				
			|||||||
use actix_web::{get, post, web, App, HttpResponse, HttpServer, Responder, HttpRequest, Result};
 | 
					 | 
				
			||||||
use actix_files::NamedFile;
 | 
					 | 
				
			||||||
use std::path::PathBuf;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#[get("/status/ok")]
 | 
					 | 
				
			||||||
async fn hello() -> impl Responder {
 | 
					 | 
				
			||||||
    HttpResponse::Ok().body("{\"status\": 200}")
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#[post("/echo")]
 | 
					 | 
				
			||||||
async fn echo(req_body: String) -> impl Responder {
 | 
					 | 
				
			||||||
    HttpResponse::Ok().body(req_body)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
async fn manual_hello() -> impl Responder {
 | 
					 | 
				
			||||||
    HttpResponse::Ok().body("Hey there!")
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
async fn static_serve(req: HttpRequest) -> Result<NamedFile> {
 | 
					 | 
				
			||||||
    let path: &str = req.path();
 | 
					 | 
				
			||||||
    let real_path = &path[1..];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    Ok(NamedFile::open(real_path)?)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#[actix_web::main]
 | 
					 | 
				
			||||||
async fn main() -> std::io::Result<()> {
 | 
					 | 
				
			||||||
    println!("Hello, world!");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    HttpServer::new(|| {
 | 
					 | 
				
			||||||
        App::new()
 | 
					 | 
				
			||||||
            .route("/static/{filename:.*}", web::get().to(static_serve))
 | 
					 | 
				
			||||||
            .service(hello)
 | 
					 | 
				
			||||||
            .service(echo)
 | 
					 | 
				
			||||||
            .route("/hey", web::get().to(manual_hello))
 | 
					 | 
				
			||||||
    })
 | 
					 | 
				
			||||||
    .bind(("0.0.0.0", 9090))?
 | 
					 | 
				
			||||||
    .run()
 | 
					 | 
				
			||||||
    .await
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,33 +0,0 @@
 | 
				
			|||||||
<!DOCTYPE html>
 | 
					 | 
				
			||||||
<html>
 | 
					 | 
				
			||||||
<head>
 | 
					 | 
				
			||||||
    <title>Welcome to nginx!</title>
 | 
					 | 
				
			||||||
    <style>
 | 
					 | 
				
			||||||
        html {
 | 
					 | 
				
			||||||
            color-scheme: light dark;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        body {
 | 
					 | 
				
			||||||
            width: 35em;
 | 
					 | 
				
			||||||
            margin: 0 auto;
 | 
					 | 
				
			||||||
            font-family: Tahoma, Verdana, Arial, sans-serif;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    </style>
 | 
					 | 
				
			||||||
</head>
 | 
					 | 
				
			||||||
<body>
 | 
					 | 
				
			||||||
    <h1>Welcome to nginx!</h1>
 | 
					 | 
				
			||||||
    <p>
 | 
					 | 
				
			||||||
        If you see this page, the nginx web server is successfully installed and
 | 
					 | 
				
			||||||
        working. Further configuration is required.
 | 
					 | 
				
			||||||
    </p>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    <p>
 | 
					 | 
				
			||||||
        For online documentation and support please refer to
 | 
					 | 
				
			||||||
        <a href="http://nginx.org/">nginx.org</a>.<br />
 | 
					 | 
				
			||||||
        Commercial support is available at
 | 
					 | 
				
			||||||
        <a href="http://nginx.com/">nginx.com</a>.
 | 
					 | 
				
			||||||
    </p>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    <p><em>Thank you for using nginx.</em></p>
 | 
					 | 
				
			||||||
</body>
 | 
					 | 
				
			||||||
</html>
 | 
					 | 
				
			||||||
							
								
								
									
										34
									
								
								FlaskAPI/.dockerignore
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								FlaskAPI/.dockerignore
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,34 @@
 | 
				
			|||||||
 | 
					# Include any files or directories that you don't want to be copied to your
 | 
				
			||||||
 | 
					# container here (e.g., local build artifacts, temporary files, etc.).
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# For more help, visit the .dockerignore file reference guide at
 | 
				
			||||||
 | 
					# https://docs.docker.com/engine/reference/builder/#dockerignore-file
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					**/.DS_Store
 | 
				
			||||||
 | 
					**/__pycache__
 | 
				
			||||||
 | 
					**/.venv
 | 
				
			||||||
 | 
					**/.classpath
 | 
				
			||||||
 | 
					**/.dockerignore
 | 
				
			||||||
 | 
					**/.env
 | 
				
			||||||
 | 
					**/.git
 | 
				
			||||||
 | 
					**/.gitignore
 | 
				
			||||||
 | 
					**/.project
 | 
				
			||||||
 | 
					**/.settings
 | 
				
			||||||
 | 
					**/.toolstarget
 | 
				
			||||||
 | 
					**/.vs
 | 
				
			||||||
 | 
					**/.vscode
 | 
				
			||||||
 | 
					**/*.*proj.user
 | 
				
			||||||
 | 
					**/*.dbmdl
 | 
				
			||||||
 | 
					**/*.jfm
 | 
				
			||||||
 | 
					**/bin
 | 
				
			||||||
 | 
					**/charts
 | 
				
			||||||
 | 
					**/docker-compose*
 | 
				
			||||||
 | 
					**/compose*
 | 
				
			||||||
 | 
					**/Dockerfile*
 | 
				
			||||||
 | 
					**/node_modules
 | 
				
			||||||
 | 
					**/npm-debug.log
 | 
				
			||||||
 | 
					**/obj
 | 
				
			||||||
 | 
					**/secrets.dev.yaml
 | 
				
			||||||
 | 
					**/values.dev.yaml
 | 
				
			||||||
 | 
					LICENSE
 | 
				
			||||||
 | 
					README.md
 | 
				
			||||||
							
								
								
									
										8
									
								
								FlaskAPI/.idea/.gitignore
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								FlaskAPI/.idea/.gitignore
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,8 @@
 | 
				
			|||||||
 | 
					# Default ignored files
 | 
				
			||||||
 | 
					/shelf/
 | 
				
			||||||
 | 
					/workspace.xml
 | 
				
			||||||
 | 
					# Editor-based HTTP Client requests
 | 
				
			||||||
 | 
					/httpRequests/
 | 
				
			||||||
 | 
					# Datasource local storage ignored files
 | 
				
			||||||
 | 
					/dataSources/
 | 
				
			||||||
 | 
					/dataSources.local.xml
 | 
				
			||||||
							
								
								
									
										19
									
								
								FlaskAPI/.idea/FlaskAPI.iml
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								FlaskAPI/.idea/FlaskAPI.iml
									
									
									
										generated
									
									
									
										Normal file
									
								
							@@ -0,0 +1,19 @@
 | 
				
			|||||||
 | 
					<?xml version="1.0" encoding="UTF-8"?>
 | 
				
			||||||
 | 
					<module type="PYTHON_MODULE" version="4">
 | 
				
			||||||
 | 
					  <component name="Flask">
 | 
				
			||||||
 | 
					    <option name="enabled" value="true" />
 | 
				
			||||||
 | 
					  </component>
 | 
				
			||||||
 | 
					  <component name="NewModuleRootManager">
 | 
				
			||||||
 | 
					    <content url="file://$MODULE_DIR$" />
 | 
				
			||||||
 | 
					    <orderEntry type="inheritedJdk" />
 | 
				
			||||||
 | 
					    <orderEntry type="sourceFolder" forTests="false" />
 | 
				
			||||||
 | 
					  </component>
 | 
				
			||||||
 | 
					  <component name="TemplatesService">
 | 
				
			||||||
 | 
					    <option name="TEMPLATE_CONFIGURATION" value="Jinja2" />
 | 
				
			||||||
 | 
					    <option name="TEMPLATE_FOLDERS">
 | 
				
			||||||
 | 
					      <list>
 | 
				
			||||||
 | 
					        <option value="$MODULE_DIR$/../FlaskAPI\templates" />
 | 
				
			||||||
 | 
					      </list>
 | 
				
			||||||
 | 
					    </option>
 | 
				
			||||||
 | 
					  </component>
 | 
				
			||||||
 | 
					</module>
 | 
				
			||||||
							
								
								
									
										6
									
								
								FlaskAPI/.idea/inspectionProfiles/profiles_settings.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								FlaskAPI/.idea/inspectionProfiles/profiles_settings.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							@@ -0,0 +1,6 @@
 | 
				
			|||||||
 | 
					<component name="InspectionProjectProfileManager">
 | 
				
			||||||
 | 
					  <settings>
 | 
				
			||||||
 | 
					    <option name="USE_PROJECT_PROFILE" value="false" />
 | 
				
			||||||
 | 
					    <version value="1.0" />
 | 
				
			||||||
 | 
					  </settings>
 | 
				
			||||||
 | 
					</component>
 | 
				
			||||||
							
								
								
									
										4
									
								
								FlaskAPI/.idea/misc.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								FlaskAPI/.idea/misc.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							@@ -0,0 +1,4 @@
 | 
				
			|||||||
 | 
					<?xml version="1.0" encoding="UTF-8"?>
 | 
				
			||||||
 | 
					<project version="4">
 | 
				
			||||||
 | 
					  <component name="ProjectRootManager" version="2" project-jdk-name="Python 3.10 (FlaskAPI)" project-jdk-type="Python SDK" />
 | 
				
			||||||
 | 
					</project>
 | 
				
			||||||
							
								
								
									
										8
									
								
								FlaskAPI/.idea/modules.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								FlaskAPI/.idea/modules.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							@@ -0,0 +1,8 @@
 | 
				
			|||||||
 | 
					<?xml version="1.0" encoding="UTF-8"?>
 | 
				
			||||||
 | 
					<project version="4">
 | 
				
			||||||
 | 
					  <component name="ProjectModuleManager">
 | 
				
			||||||
 | 
					    <modules>
 | 
				
			||||||
 | 
					      <module fileurl="file://$PROJECT_DIR$/.idea/FlaskAPI.iml" filepath="$PROJECT_DIR$/.idea/FlaskAPI.iml" />
 | 
				
			||||||
 | 
					    </modules>
 | 
				
			||||||
 | 
					  </component>
 | 
				
			||||||
 | 
					</project>
 | 
				
			||||||
							
								
								
									
										17
									
								
								FlaskAPI/.vscode/launch.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								FlaskAPI/.vscode/launch.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,17 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					  "version": "0.0.1",
 | 
				
			||||||
 | 
					  "configurations": [
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "name": "Python: Flask",
 | 
				
			||||||
 | 
					      "type": "python",
 | 
				
			||||||
 | 
					      "request": "launch",
 | 
				
			||||||
 | 
					      "module": "flask",
 | 
				
			||||||
 | 
					      "env": { "FLASK_APP": "app.py", "FLASK_DEBUG": "1" },
 | 
				
			||||||
 | 
					      "args": ["run", "--no-debugger", "--no-reload"],
 | 
				
			||||||
 | 
					      "jinja": true,
 | 
				
			||||||
 | 
					      "justMyCode": true
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ]
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										0
									
								
								FlaskAPI/.vscode/settings.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								FlaskAPI/.vscode/settings.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
								
								
									
										45
									
								
								FlaskAPI/Dockerfile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								FlaskAPI/Dockerfile
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,45 @@
 | 
				
			|||||||
 | 
					# syntax=docker/dockerfile:1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Comments are provided throughout this file to help you get started.
 | 
				
			||||||
 | 
					# If you need more help, visit the Dockerfile reference guide at
 | 
				
			||||||
 | 
					# https://docs.docker.com/engine/reference/builder/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ARG PYTHON_VERSION=3.10.12
 | 
				
			||||||
 | 
					FROM python:${PYTHON_VERSION}-slim as base
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Prevents Python from writing pyc files.
 | 
				
			||||||
 | 
					ENV PYTHONDONTWRITEBYTECODE=1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Keeps Python from buffering stdout and stderr to avoid situations where
 | 
				
			||||||
 | 
					# the application crashes without emitting any logs due to buffering.
 | 
				
			||||||
 | 
					ENV PYTHONUNBUFFERED=1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					WORKDIR /app
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Copy the source code into the container.
 | 
				
			||||||
 | 
					COPY . .
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					RUN apt-get update && apt-get install -y imagemagick && apt-get install -y wget && ls
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					RUN wget https://files.ivanch.me/api/public/dl/iFuXSNhw/small-image.png && \
 | 
				
			||||||
 | 
					    wget https://files.ivanch.me/api/public/dl/81Bkht5C/big-image.png && \
 | 
				
			||||||
 | 
					    wget https://files.ivanch.me/api/public/dl/nAndfAjK/video.mp4 && \
 | 
				
			||||||
 | 
					    rm -rf runtimes && \
 | 
				
			||||||
 | 
					    mkdir -p ./static && \
 | 
				
			||||||
 | 
					    mv small-image.png ./static && \
 | 
				
			||||||
 | 
					    mv big-image.png ./static && \
 | 
				
			||||||
 | 
					    mv video.mp4 ./static
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Download dependencies as a separate step to take advantage of Docker's caching.
 | 
				
			||||||
 | 
					# Leverage a cache mount to /root/.cache/pip to speed up subsequent builds.
 | 
				
			||||||
 | 
					# Leverage a bind mount to requirements.txt to avoid having to copy them into
 | 
				
			||||||
 | 
					# into this layer.
 | 
				
			||||||
 | 
					RUN --mount=type=cache,target=/root/.cache/pip \
 | 
				
			||||||
 | 
					    --mount=type=bind,source=requirements.txt,target=requirements.txt \
 | 
				
			||||||
 | 
					    python -m pip install -r requirements.txt
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Expose the port that the application listens on.
 | 
				
			||||||
 | 
					EXPOSE 5000
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Run the application.
 | 
				
			||||||
 | 
					CMD gunicorn 'app:app' --bind=0.0.0.0:5000
 | 
				
			||||||
							
								
								
									
										
											BIN
										
									
								
								FlaskAPI/__pycache__/app.cpython-310.pyc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								FlaskAPI/__pycache__/app.cpython-310.pyc
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										12
									
								
								FlaskAPI/app.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								FlaskAPI/app.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,12 @@
 | 
				
			|||||||
 | 
					from flask import Flask
 | 
				
			||||||
 | 
					from controllers.status import status_blueprint
 | 
				
			||||||
 | 
					from controllers.image import image_blueprint
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					app = Flask(__name__)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if __name__ == '__main__':
 | 
				
			||||||
 | 
					    app.run()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					app.register_blueprint(status_blueprint)
 | 
				
			||||||
 | 
					app.register_blueprint(image_blueprint)
 | 
				
			||||||
							
								
								
									
										
											BIN
										
									
								
								FlaskAPI/blurred_temp_image.jpeg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								FlaskAPI/blurred_temp_image.jpeg
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 36 KiB  | 
							
								
								
									
										49
									
								
								FlaskAPI/compose.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								FlaskAPI/compose.yaml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,49 @@
 | 
				
			|||||||
 | 
					# Comments are provided throughout this file to help you get started.
 | 
				
			||||||
 | 
					# If you need more help, visit the Docker compose reference guide at
 | 
				
			||||||
 | 
					# https://docs.docker.com/compose/compose-file/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Here the instructions define your application as a service called "server".
 | 
				
			||||||
 | 
					# This service is built from the Dockerfile in the current directory.
 | 
				
			||||||
 | 
					# You can add other services your application may depend on here, such as a
 | 
				
			||||||
 | 
					# database or a cache. For examples, see the Awesome Compose repository:
 | 
				
			||||||
 | 
					# https://github.com/docker/awesome-compose
 | 
				
			||||||
 | 
					services:
 | 
				
			||||||
 | 
					  server:
 | 
				
			||||||
 | 
					    build:
 | 
				
			||||||
 | 
					      context: .
 | 
				
			||||||
 | 
					    ports:
 | 
				
			||||||
 | 
					      - 5000:5000
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# The commented out section below is an example of how to define a PostgreSQL
 | 
				
			||||||
 | 
					# database that your application can use. `depends_on` tells Docker Compose to
 | 
				
			||||||
 | 
					# start the database before your application. The `db-data` volume persists the
 | 
				
			||||||
 | 
					# database data between container restarts. The `db-password` secret is used
 | 
				
			||||||
 | 
					# to set the database password. You must create `db/password.txt` and add
 | 
				
			||||||
 | 
					# a password of your choosing to it before running `docker compose up`.
 | 
				
			||||||
 | 
					#     depends_on:
 | 
				
			||||||
 | 
					#       db:
 | 
				
			||||||
 | 
					#         condition: service_healthy
 | 
				
			||||||
 | 
					#   db:
 | 
				
			||||||
 | 
					#     image: postgres
 | 
				
			||||||
 | 
					#     restart: always
 | 
				
			||||||
 | 
					#     user: postgres
 | 
				
			||||||
 | 
					#     secrets:
 | 
				
			||||||
 | 
					#       - db-password
 | 
				
			||||||
 | 
					#     volumes:
 | 
				
			||||||
 | 
					#       - db-data:/var/lib/postgresql/data
 | 
				
			||||||
 | 
					#     environment:
 | 
				
			||||||
 | 
					#       - POSTGRES_DB=example
 | 
				
			||||||
 | 
					#       - POSTGRES_PASSWORD_FILE=/run/secrets/db-password
 | 
				
			||||||
 | 
					#     expose:
 | 
				
			||||||
 | 
					#       - 5432
 | 
				
			||||||
 | 
					#     healthcheck:
 | 
				
			||||||
 | 
					#       test: [ "CMD", "pg_isready" ]
 | 
				
			||||||
 | 
					#       interval: 10s
 | 
				
			||||||
 | 
					#       timeout: 5s
 | 
				
			||||||
 | 
					#       retries: 5
 | 
				
			||||||
 | 
					# volumes:
 | 
				
			||||||
 | 
					#   db-data:
 | 
				
			||||||
 | 
					# secrets:
 | 
				
			||||||
 | 
					#   db-password:
 | 
				
			||||||
 | 
					#     file: db/password.txt
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										
											BIN
										
									
								
								FlaskAPI/controllers/__pycache__/image.cpython-310.pyc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								FlaskAPI/controllers/__pycache__/image.cpython-310.pyc
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								FlaskAPI/controllers/__pycache__/status.cpython-310.pyc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								FlaskAPI/controllers/__pycache__/status.cpython-310.pyc
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										41
									
								
								FlaskAPI/controllers/image.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								FlaskAPI/controllers/image.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,41 @@
 | 
				
			|||||||
 | 
					from services.image import ImageService
 | 
				
			||||||
 | 
					from static.image_helper import ImageHelper
 | 
				
			||||||
 | 
					from flask import request, Response, Blueprint, jsonify, send_file
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					image_blueprint = Blueprint('image_blueprint', __name__)
 | 
				
			||||||
 | 
					image_service = ImageService()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@image_blueprint.route('/image/blur', methods=['POST'])
 | 
				
			||||||
 | 
					def blur_image():
 | 
				
			||||||
 | 
					    radius = int(request.form.get('radius'))
 | 
				
			||||||
 | 
					    image = request.files.get('file')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if radius and image:
 | 
				
			||||||
 | 
					        return send_file(image_service.box_blur_image(image, radius),
 | 
				
			||||||
 | 
					                         mimetype='image/jpeg',
 | 
				
			||||||
 | 
					                         as_attachment=True,
 | 
				
			||||||
 | 
					                         download_name='blurred_image.jpeg')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return "Bad request", 400
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@image_blueprint.route('/image/load-small-image', methods=['GET'])
 | 
				
			||||||
 | 
					def get_simple_image():
 | 
				
			||||||
 | 
					    return send_file(image_service.get_simple_image(),
 | 
				
			||||||
 | 
					                     mimetype='image/png',
 | 
				
			||||||
 | 
					                     as_attachment=True,
 | 
				
			||||||
 | 
					                     download_name='small-image.png')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@image_blueprint.route('/image/load-big-image', methods=['GET'])
 | 
				
			||||||
 | 
					def get_big_image():
 | 
				
			||||||
 | 
					    return send_file(image_service.get_big_image(),
 | 
				
			||||||
 | 
					                     mimetype='image/png',
 | 
				
			||||||
 | 
					                     as_attachment=True,
 | 
				
			||||||
 | 
					                     download_name='big-image.png')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@image_blueprint.route('/image/save-big-image', methods=['POST'])
 | 
				
			||||||
 | 
					def save_image():
 | 
				
			||||||
 | 
					    pass
 | 
				
			||||||
							
								
								
									
										19
									
								
								FlaskAPI/controllers/status.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								FlaskAPI/controllers/status.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,19 @@
 | 
				
			|||||||
 | 
					from flask import jsonify, Blueprint
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					status_blueprint = Blueprint('status_blueprint', __name__)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class StatusController:
 | 
				
			||||||
 | 
					    def __init__(self):
 | 
				
			||||||
 | 
					        pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def return_ok(self):
 | 
				
			||||||
 | 
					        return jsonify(status=200)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					status_controller = StatusController()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@status_blueprint.route('/status/ok', methods=['GET'])
 | 
				
			||||||
 | 
					def return_ok():
 | 
				
			||||||
 | 
					    return jsonify(status=200)
 | 
				
			||||||
							
								
								
									
										3
									
								
								FlaskAPI/requirements.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								FlaskAPI/requirements.txt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
				
			|||||||
 | 
					Flask>=1.0
 | 
				
			||||||
 | 
					gunicorn>=19.9.0
 | 
				
			||||||
 | 
					Wand
 | 
				
			||||||
							
								
								
									
										
											BIN
										
									
								
								FlaskAPI/services/__pycache__/image.cpython-310.pyc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								FlaskAPI/services/__pycache__/image.cpython-310.pyc
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										69
									
								
								FlaskAPI/services/image.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								FlaskAPI/services/image.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,69 @@
 | 
				
			|||||||
 | 
					from wand.image import Image
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from static.image_helper import ImageHelper
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def box_blur_image_separable(image, blurred_image, radius_x, radius_y):
 | 
				
			||||||
 | 
					    pixels = image.get_pixels()
 | 
				
			||||||
 | 
					    blurred_pixels = blurred_image.get_pixels()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for pixel in pixels:
 | 
				
			||||||
 | 
					        x, y = pixel[0], pixel[1]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        r_total, g_total, b_total = 0, 0, 0
 | 
				
			||||||
 | 
					        pixel_count = 0
 | 
				
			||||||
 | 
					        for offset_y in range(-radius_y, radius_y + 1):
 | 
				
			||||||
 | 
					            for offset_x in range(-radius_x, radius_x + 1):
 | 
				
			||||||
 | 
					                new_x = x + offset_x
 | 
				
			||||||
 | 
					                new_y = y + offset_y
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if 0 <= new_x < image.width and 0 <= new_y < image.height:
 | 
				
			||||||
 | 
					                    pixel_color = pixels[new_y * image.width + new_x]
 | 
				
			||||||
 | 
					                    r_total += pixel_color.red
 | 
				
			||||||
 | 
					                    g_total += pixel_color.green
 | 
				
			||||||
 | 
					                    b_total += pixel_color.blue
 | 
				
			||||||
 | 
					                    pixel_count += 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        blurred_pixel = blurred_pixels[y * image.width + x]
 | 
				
			||||||
 | 
					        blurred_pixel.red = int(r_total / pixel_count)
 | 
				
			||||||
 | 
					        blurred_pixel.green = int(g_total / pixel_count)
 | 
				
			||||||
 | 
					        blurred_pixel.blue = int(b_total / pixel_count)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return blurred_image
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def save_image(file_stream):
 | 
				
			||||||
 | 
					    with open("image.png", "wb") as file:
 | 
				
			||||||
 | 
					        file.write(file_stream.read())
 | 
				
			||||||
 | 
					        file.close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ImageService:
 | 
				
			||||||
 | 
					    def __init__(self):
 | 
				
			||||||
 | 
					        pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def box_blur_image(self, img, radius):
 | 
				
			||||||
 | 
					        temp_path = 'temp_image.png'
 | 
				
			||||||
 | 
					        img.save(temp_path)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        with Image(filename=temp_path) as img:
 | 
				
			||||||
 | 
					            img.blur(radius, 2)
 | 
				
			||||||
 | 
					            blurred_temp_path = 'blurred_temp_image.png'
 | 
				
			||||||
 | 
					            img.save(filename='blurred_temp_image.png')
 | 
				
			||||||
 | 
					            return blurred_temp_path
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def get_simple_image(self):
 | 
				
			||||||
 | 
					        with ImageHelper.SimpleImage as img:
 | 
				
			||||||
 | 
					            img = ImageHelper.SimpleImage
 | 
				
			||||||
 | 
					            simple_image = 'simple_image.png'
 | 
				
			||||||
 | 
					            img.save(filename='simple_image.png')
 | 
				
			||||||
 | 
					            return simple_image
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def get_big_image(self):
 | 
				
			||||||
 | 
					        with ImageHelper.BigImage as img:
 | 
				
			||||||
 | 
					            img = ImageHelper.BigImage
 | 
				
			||||||
 | 
					            big_image = 'big_image.png'
 | 
				
			||||||
 | 
					            img.save(filename='big_image.png')
 | 
				
			||||||
 | 
					            return big_image
 | 
				
			||||||
							
								
								
									
										
											BIN
										
									
								
								FlaskAPI/static/__pycache__/image_helper.cpython-310.pyc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								FlaskAPI/static/__pycache__/image_helper.cpython-310.pyc
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										17
									
								
								FlaskAPI/static/image_helper.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								FlaskAPI/static/image_helper.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,17 @@
 | 
				
			|||||||
 | 
					from wand.image import Image
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ImageHelper:
 | 
				
			||||||
 | 
					    SimpleImage = None
 | 
				
			||||||
 | 
					    BigImage = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @staticmethod
 | 
				
			||||||
 | 
					    def load_images():
 | 
				
			||||||
 | 
					        ImageHelper.SimpleImage = Image(filename="./static/small-image.png")
 | 
				
			||||||
 | 
					        #ImageHelper.SimpleImage.save(filename="./static/small-image.png")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        ImageHelper.BigImage = Image(filename="./static/big-image.png")
 | 
				
			||||||
 | 
					        #ImageHelper.BigImage.save(filename="./static/big-image.png")
 | 
				
			||||||
 | 
					        pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ImageHelper.load_images()
 | 
				
			||||||
							
								
								
									
										
											BIN
										
									
								
								FlaskAPI/temp_image.jpeg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								FlaskAPI/temp_image.jpeg
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 44 KiB  | 
@@ -1,89 +0,0 @@
 | 
				
			|||||||
import numpy as np
 | 
					 | 
				
			||||||
import matplotlib.pyplot as plt
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def plot_graph(x, y, title, x_label, y_label, filename):
 | 
					 | 
				
			||||||
    plt.plot(x, y, 'ro', markersize=1, linewidth=0.5, linestyle='solid')
 | 
					 | 
				
			||||||
    plt.title(title)
 | 
					 | 
				
			||||||
    plt.xlabel(x_label)
 | 
					 | 
				
			||||||
    plt.ylabel(y_label)
 | 
					 | 
				
			||||||
    plt.savefig(f'{filename}.png')
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    plt.clf()
 | 
					 | 
				
			||||||
    plt.close('all')
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def plot_resource_graph(x_data, y_data, title, x_label, y_label, filename):
 | 
					 | 
				
			||||||
    requests = x_data
 | 
					 | 
				
			||||||
    resource = {
 | 
					 | 
				
			||||||
        'CPU': [p[0] for p in y_data],
 | 
					 | 
				
			||||||
        'RAM': [p[1] for p in y_data],
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    x = np.arange(len(requests))
 | 
					 | 
				
			||||||
    width = 0.25
 | 
					 | 
				
			||||||
    multiplier = 0
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    fig, ax = plt.subplots(layout='constrained')
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    for attribute, measurement in resource.items():
 | 
					 | 
				
			||||||
        offset = width * multiplier
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        rects = ax.bar(x + offset, measurement, width, label=attribute)
 | 
					 | 
				
			||||||
        ax.bar_label(rects, padding=3)
 | 
					 | 
				
			||||||
        multiplier += 1
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # Add some text for labels, title and custom x-axis tick labels, etc.
 | 
					 | 
				
			||||||
    ax.set_xlabel(x_label)
 | 
					 | 
				
			||||||
    ax.set_ylabel(y_label)
 | 
					 | 
				
			||||||
    ax.set_title(title)
 | 
					 | 
				
			||||||
    ax.set_xticks(x + (width/2), requests)
 | 
					 | 
				
			||||||
    ax.legend(loc='upper left', ncols=len(resource.items()))
 | 
					 | 
				
			||||||
    ax.set_ylim(0, 100)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    plt.savefig(f'{filename}.png')
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    plt.clf()
 | 
					 | 
				
			||||||
    plt.close('all')
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def get_data(filename):
 | 
					 | 
				
			||||||
    lines = []
 | 
					 | 
				
			||||||
    with open(filename, 'r') as f:
 | 
					 | 
				
			||||||
        lines = f.readlines()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    x = []
 | 
					 | 
				
			||||||
    y = []
 | 
					 | 
				
			||||||
    for line in lines:
 | 
					 | 
				
			||||||
        line = line.strip().split(',')
 | 
					 | 
				
			||||||
        if line:
 | 
					 | 
				
			||||||
            x.append(int(line[0]))
 | 
					 | 
				
			||||||
            y.append(float(line[1]))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return x, y
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def get_resource_data(filename):
 | 
					 | 
				
			||||||
    lines = []
 | 
					 | 
				
			||||||
    with open(filename, 'r') as f:
 | 
					 | 
				
			||||||
        lines = f.readlines()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    x = []
 | 
					 | 
				
			||||||
    y = []
 | 
					 | 
				
			||||||
    for line in lines:
 | 
					 | 
				
			||||||
        line = line.strip().split(',')
 | 
					 | 
				
			||||||
        if line:
 | 
					 | 
				
			||||||
            x.append(int(line[0])) # requests
 | 
					 | 
				
			||||||
            y.append([float(v)*100 for v in line[1:]]) # cpu, ram
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return x, y
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def generate_req_graph(filename, framework_name, endpoint_name):
 | 
					 | 
				
			||||||
    x, y = get_data(filename)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    filename = filename.split('/')[-1]
 | 
					 | 
				
			||||||
    new_filename = filename.replace('.csv', '')
 | 
					 | 
				
			||||||
    plot_graph(x, y, f'{framework_name} - {endpoint_name}', 'Número de requisições', 'Requisições por segundo', new_filename)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def generate_resource_graph(filename, framework_name, endpoint_name):
 | 
					 | 
				
			||||||
    x, y = get_resource_data(filename)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    filename = filename.split('/')[-1]
 | 
					 | 
				
			||||||
    new_filename = filename.replace('.csv', '')
 | 
					 | 
				
			||||||
    plot_resource_graph(x, y, f'{framework_name} - {endpoint_name}', 'Uso de recursos', 'Uso (%)', new_filename)
 | 
					 | 
				
			||||||
@@ -1,17 +0,0 @@
 | 
				
			|||||||
import requests
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def download_file(url):
 | 
					 | 
				
			||||||
    local_filename = url.split('/')[-1]
 | 
					 | 
				
			||||||
    with requests.get(url, stream=True) as r:
 | 
					 | 
				
			||||||
        r.raise_for_status()
 | 
					 | 
				
			||||||
        with open(local_filename, 'wb') as f:
 | 
					 | 
				
			||||||
            for chunk in r.iter_content(chunk_size=8192):
 | 
					 | 
				
			||||||
                # If you have chunk encoded response uncomment if
 | 
					 | 
				
			||||||
                # and set chunk_size parameter to None.
 | 
					 | 
				
			||||||
                #if chunk:
 | 
					 | 
				
			||||||
                f.write(chunk)
 | 
					 | 
				
			||||||
    return local_filename
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def init():
 | 
					 | 
				
			||||||
    download_file('https://files.ivanch.me/api/public/dl/Dj0gkp-m/small-image.png')
 | 
					 | 
				
			||||||
    download_file('https://files.ivanch.me/api/public/dl/FqHEPM1Q/big-image.png')
 | 
					 | 
				
			||||||
@@ -1,155 +1,33 @@
 | 
				
			|||||||
import requests
 | 
					import requests
 | 
				
			||||||
import docker
 | 
					 | 
				
			||||||
import concurrent.futures
 | 
					import concurrent.futures
 | 
				
			||||||
import time
 | 
					import time
 | 
				
			||||||
import sys
 | 
					 | 
				
			||||||
import os
 | 
					 | 
				
			||||||
from graph import generate_req_graph, generate_resource_graph
 | 
					 | 
				
			||||||
from math import floor
 | 
					 | 
				
			||||||
from init import init
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
if len(sys.argv) < 2 or len(sys.argv) > 3 or sys.argv[1] == '-h' or sys.argv[1] == '--help':
 | 
					URL_BASE = 'http://localhost:5100'
 | 
				
			||||||
    print("Usage: python testes.py <framework name> [container name]")
 | 
					 | 
				
			||||||
    sys.exit(1)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
init()
 | 
					num_requests = [1000, 5000, 10_000, 50_000, 100_000, 500_000, 1_000_000]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
THREADS = 10
 | 
					def send_request(session, url):
 | 
				
			||||||
FRAMEWORK_NAME = sys.argv[1]
 | 
					    response = session.get(url)
 | 
				
			||||||
CONTAINER_NAME = sys.argv[2] if len(sys.argv) > 2 else ""
 | 
					    return response.status_code
 | 
				
			||||||
URL_BASE = 'http://localhost:9090'
 | 
					 | 
				
			||||||
BLUR_RADIUS = 5
 | 
					 | 
				
			||||||
API_REQUESTS = [
 | 
					 | 
				
			||||||
    ('/image/save-big-image', 'POST', range(0, 10_000, 1_000), open('big-image.png', 'rb').read()),
 | 
					 | 
				
			||||||
    (f'/image/blur?radius={BLUR_RADIUS}', 'POST', range(0, 1_000, 50), open('small-image.png', 'rb').read()),
 | 
					 | 
				
			||||||
    ('/status/ok', 'GET', range(0, 30_000, 5000), None),
 | 
					 | 
				
			||||||
    ('/image/load-small-image', 'GET', range(0, 30_000, 5000), None),
 | 
					 | 
				
			||||||
    ('/static/small-image.png', 'GET', range(0, 30_000, 5000), None),
 | 
					 | 
				
			||||||
    ('/image/load-big-image', 'GET', range(0, 500, 50), None),
 | 
					 | 
				
			||||||
    ('/static/big-image.png', 'GET', range(0, 500, 50), None),
 | 
					 | 
				
			||||||
    ('/static/video.mp4', 'GET', range(0, 10_000, 1_000), None),
 | 
					 | 
				
			||||||
]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def send_request(url, method = 'GET', payload = None):
 | 
					 | 
				
			||||||
    success = False
 | 
					 | 
				
			||||||
    responses = {
 | 
					 | 
				
			||||||
        2: 0, # OK
 | 
					 | 
				
			||||||
        4: 0, # Bad Request
 | 
					 | 
				
			||||||
        5: 0, # Server Error
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    while not success:
 | 
					 | 
				
			||||||
        try:
 | 
					 | 
				
			||||||
            response = None
 | 
					 | 
				
			||||||
            if method == 'GET':
 | 
					 | 
				
			||||||
                response = requests.get(url)
 | 
					 | 
				
			||||||
            elif method == 'POST':
 | 
					 | 
				
			||||||
                response = requests.post(url, data=payload, headers={'Content-Type': 'image/png'})
 | 
					 | 
				
			||||||
        except:
 | 
					 | 
				
			||||||
            continue
 | 
					 | 
				
			||||||
        success = response.status_code == 200
 | 
					 | 
				
			||||||
        responses[floor(response.status_code/100)] += 1
 | 
					 | 
				
			||||||
    return responses
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def getFileNames(endpoint):
 | 
					 | 
				
			||||||
    endpoint = endpoint.replace('/', '')
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    files = [
 | 
					 | 
				
			||||||
        f"data/req_{FRAMEWORK_NAME}_{endpoint}.csv",
 | 
					 | 
				
			||||||
        f"data/resource_{FRAMEWORK_NAME}_{endpoint}.csv",
 | 
					 | 
				
			||||||
    ]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return files
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def record(filename, requests, reqpersec):
 | 
					 | 
				
			||||||
    with open(filename, "a") as file:
 | 
					 | 
				
			||||||
        file.write(f"{requests},{reqpersec}\n")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def record_resource(filename, requests, cpu, ram):
 | 
					 | 
				
			||||||
    with open(filename, "a") as file:
 | 
					 | 
				
			||||||
        file.write(f"{requests},{cpu},{ram}\n")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def run_tests(endpoint, method, num_requests, metadata):
 | 
					 | 
				
			||||||
    files = getFileNames(endpoint)
 | 
					 | 
				
			||||||
    for filename in files:
 | 
					 | 
				
			||||||
        if os.path.exists(filename):
 | 
					 | 
				
			||||||
            os.remove(filename)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def main():
 | 
				
			||||||
    for num_request in num_requests:
 | 
					    for num_request in num_requests:
 | 
				
			||||||
        if num_request <= 0: continue
 | 
					        with concurrent.futures.ThreadPoolExecutor(max_workers=10) as executor:
 | 
				
			||||||
 | 
					            url = f'{URL_BASE}/status/ok'
 | 
				
			||||||
        ok_responses = 0
 | 
					 | 
				
			||||||
        bad_responses = 0
 | 
					 | 
				
			||||||
        server_errors = 0
 | 
					 | 
				
			||||||
        cpu, ram = 0, 0
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        with concurrent.futures.ThreadPoolExecutor(max_workers=THREADS) as executor:
 | 
					 | 
				
			||||||
            url = f'{URL_BASE}{endpoint}'
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            start_time = time.time()
 | 
					            start_time = time.time()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            futures = []
 | 
					            futures = []
 | 
				
			||||||
            #with requests.Session() as session:
 | 
					            with requests.Session() as session:
 | 
				
			||||||
            #    futures = [executor.submit(send_request, session, url) for _ in range(num_request)]
 | 
					                futures = [executor.submit(send_request, session, url) for _ in range(num_request)]
 | 
				
			||||||
 | 
					 | 
				
			||||||
            half = floor(num_request/2)
 | 
					 | 
				
			||||||
            for i in range(num_request):
 | 
					 | 
				
			||||||
                futures.append(executor.submit(send_request, url, method, metadata))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                if i == half:
 | 
					 | 
				
			||||||
                    cpu, ram = get_resource_usage()
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            concurrent.futures.wait(futures)
 | 
					            concurrent.futures.wait(futures)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            elapsed_time = time.time() - start_time
 | 
					            elapsed_time = time.time() - start_time
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            for future in futures:
 | 
					            successful_responses = sum(1 for future in futures if future.result() == 200)
 | 
				
			||||||
                responses = future.result()
 | 
					 | 
				
			||||||
                ok_responses += responses[2]
 | 
					 | 
				
			||||||
                bad_responses += responses[4]
 | 
					 | 
				
			||||||
                server_errors += responses[5]
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        print(f"{num_request}: {elapsed_time:.2f} seconds. {elapsed_time/num_request:.4f} seconds per request. {num_request/elapsed_time:.2f} requests per second. [OK: {ok_responses}, Bad Request: {bad_responses}, Server Error: {server_errors}]]")
 | 
					        print(f"All requests completed in {elapsed_time:.2f} seconds. {elapsed_time/num_request:.4f} seconds per request. {num_request/elapsed_time:.2f} requests per second.")
 | 
				
			||||||
        record(files[0], num_request, f"{num_request/elapsed_time:.2f}")
 | 
					        print(f"Successful responses: {successful_responses}/{num_request}")
 | 
				
			||||||
        record_resource(files[1], num_request, cpu, ram)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        generate_req_graph(files[0], FRAMEWORK_NAME, endpoint)
 | 
					main()
 | 
				
			||||||
        generate_resource_graph(files[1], FRAMEWORK_NAME, endpoint)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        time.sleep(3)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def get_resource_usage():
 | 
					 | 
				
			||||||
    if CONTAINER_NAME == "": return 0, 0
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    try:
 | 
					 | 
				
			||||||
        client = docker.from_env()
 | 
					 | 
				
			||||||
        stats = client.containers.get(CONTAINER_NAME).stats(stream=False)
 | 
					 | 
				
			||||||
    except:
 | 
					 | 
				
			||||||
        return 0, 0 # unable to get stats
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return get_cpu_usage(stats), get_ram_usage(stats)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def get_cpu_usage(stats):
 | 
					 | 
				
			||||||
    UsageDelta = stats['cpu_stats']['cpu_usage']['total_usage'] - stats['precpu_stats']['cpu_usage']['total_usage']
 | 
					 | 
				
			||||||
    SystemDelta = stats['cpu_stats']['system_cpu_usage'] - stats['precpu_stats']['system_cpu_usage']
 | 
					 | 
				
			||||||
    len_cpu = stats['cpu_stats']['online_cpus']
 | 
					 | 
				
			||||||
    percentage = (UsageDelta / SystemDelta) * len_cpu
 | 
					 | 
				
			||||||
    return f"{percentage:.2f}"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def get_ram_usage(stats):
 | 
					 | 
				
			||||||
    usage = stats['memory_stats']['usage']
 | 
					 | 
				
			||||||
    limit = stats['memory_stats']['limit']
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    percentage = (usage / limit)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # percent = round(percentage, 2)
 | 
					 | 
				
			||||||
    return f"{percentage:.2f}"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
if __name__ == "__main__":
 | 
					 | 
				
			||||||
    if not os.path.exists("data"):
 | 
					 | 
				
			||||||
        os.mkdir("data")
 | 
					 | 
				
			||||||
    else:
 | 
					 | 
				
			||||||
        os.system("rm -rf data/*")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    for endpoint, method, num_requests, metadata in API_REQUESTS:
 | 
					 | 
				
			||||||
        print(f"# {endpoint}")
 | 
					 | 
				
			||||||
        run_tests(endpoint, method, num_requests, metadata)
 | 
					 | 
				
			||||||
		Reference in New Issue
	
	Block a user