How to get a image/png with Ktor client get request? - kotlin

I am trying to do a get request from a client get call to my server. My server response with a image/png content type. How can I recieve the image from my kotlin code?

You can download not only an image but also any other file.
Create ktor-client as you usually do.
val client = HttpClient(OkHttp) {
install(ContentNegotiation) {
json(Json { isLenient = true; ignoreUnknownKeys = true })
}
}
For downloading a file using this client, read response using bodyAsChannel() which reads the response as ByteReadChannel. Use copyAsChannel() to write the data on the disk, passing destination's ByteWriteChannel.
GlobalScope.launch(Dispatchers.IO) {
val url = Url("FILE_DOWNLOAD_LINK")
val file = File(url.pathSegments.last())
client.get(url).bodyAsChannel().copyAndClose(file.writeChannel())
println("Finished downloading..")
}

You're going to want to serve static content from your Ktor server: https://ktor.io/docs/serving-static-content.html
You create a static folder, then put your images in there:
static("/") {
staticRootFolder = File("files")
}
After that's set up, you can reference files in that folder. If you want files in subfolders as well, you can add an extra files(".") line:
static("/") {
staticRootFolder = File("files")
files(".")
}

Related

How to add an attachment to Testrail using the Testrail API

I have tried the following API endpoint to add an attachment to Testrail via their API.
But it is not very clear how to name the said file attachment (I am using Postman)
API endpoint:
[POST]
https:///{{testrail link}}/index.php?/api/v2/add_attachment_to_result/449
Headers:
{
"Content-Type","value":"multipart/form-data"
}
What must the body params be?
I have currently selected the file and multipart/form-data for Content-type. Please help!
The error right now on Postman :
{
"error": "No file attached or upload size was exceeded."
}
The upload size is just fine (under 256 MB)
using postman you need to pass the file through the body by adding a file type key named 'attachment' and value:{select your file}
eg:
key: attachment | value:myfile.txt
Here is a working Java example - I know it's a little late, but it may be useful for reference:
public void uploadScreenshot(long resultId, String screenshotFile) {
String url = String.format("add_attachment_to_result/%d", resultId);
try {
client.sendPost(url, screenshot);
}
catch(Exception e) {
e.printStackTrace();
}
}
You can add an attachment to various assets within TestRail, in this example I am adding a screenshot to a result, which has to be passed in (when you add a result you can get the JSON response and store the 'id' of the newly created result.

Adding HTTP Security Headers Using Lambda#Edge and Amazon CloudFront for All routes (error routes)

I am using this doc https://aws.amazon.com/blogs/networking-and-content-delivery/adding-http-security-headers-using-lambdaedge-and-amazon-cloudfront/
I am using a react app in S3 bucket, with a cloudfront CDN. I have added a lambdaedge to add a security header
headers['x-frame-options'] = [{key: 'X-Frame-Options', value: 'DENY'}];
headers['x-xss-protection'] = [{key: 'X-XSS-Protection', value: '1; mode=block'}];
It is working fine for the homepage (mySite.com):
But it doesn't work for a different route, example mySite.com/login
When I check the error behavior in cloudFront, there are no options to add a header
Why this page /login is in error? Because of react router doesn't work in aws s3 bucket
The way that I solved this was to implement an origin request Lambda#Edge function that validates the event.Records[0].cf.request.uri value against a whitelist of known files and paths in the S3 origin. If the path doesn't match the whitelist, it updates the uri value to /index.html which allows the React app handle the request.
With this change, there will no longer be any 404 requests, which means the response will successfully pass through the origin response Lambda#Edge function which adds the response headers.
We solve this by using this feature called policy response headers in cloudfront. It add headers in all cases even in error response.
Doc: https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/using-managed-response-headers-policies.html
We implemented it with terraform
resource "aws_cloudfront_response_headers_policy" "my_name" {
name = "policy-response-headers-my-name"
comment = "Add security headers to responses"
security_headers_config {
xss_protection {
mode_block = true
override = true
protection = true
}
frame_options {
frame_option = "DENY"
override = true
}
content_type_options {
override = true
}
content_security_policy {
content_security_policy = "frame-ancestors 'none'"
override = true
}
referrer_policy {
referrer_policy = "same-origin"
override = true
}
strict_transport_security {
access_control_max_age_sec = 63072000
override = true
}
origin_override = true
}
}

Access encodingResult when uploading with Alamofire 5

I'm trying to update my app to Alamofire 5 and having difficulties due to a hack-ish way I'm using it I guess.
Anyhow, I need background uploads and Alamofire is not really designed to do this. Even so, I was using it to create a properly formatted file containing multipart form so I can give it to the OS to upload in the background later.
I'll post the code doing this in Alamofire 4, my question is how can I get the url of the file I was previously getting with encodingResults?
// We're not actually going to upload photo via alamofire. It does not offer support for background uploads.
// Still we can use it to create a request and more importantly properly formatted file containing multipart form
Api.alamofire.upload(
multipartFormData: { multipartFormData in
multipartFormData.append(imageData, withName: "photo[image]", fileName: filename, mimeType: "image/jpg")
},
to: "http://", // if we give it a real url sometimes alamofire will attempt the first upload. I don't want to let it get to our servers but it fails if I feed it ""
usingThreshold: UInt64(0), // force alamofire to always write to file no matter how small the payload is
method: .post,
headers: Api.requestHeaders,
encodingCompletion: { encodingResult in
switch encodingResult {
case .success(let alamofireUploadTask, _, let url):
alamofireUploadTask.suspend()
defer { alamofireUploadTask.cancel() }
if let alamofireUploadFileUrl = url {
// we want to own the multipart file to avoid alamofire deleting it when we tell it to cancel its task
let fileUrl = ourFileUrl
do {
try FileManager.default.copyItem(at: alamofireUploadFileUrl, to: fileUrl)
// use the file we just created for a background upload
} catch {
}
}
case .failure:
// alamofire failed to encode the request file for some reason
}
}
)
Multipart encoding is fully integrated into the now-asynchronous request pipeline in Alamofire 5. That means there's no separate step to use. However, you can use the MultipartFormData type directly, just like you would in the request closure.
let data = MultipartFormData()
data.append(Data(), withName: "dataName")
try data.encode()

Correct code to upload local file to S3 proxy of API Gateway

I created an API function to work with S3. I imported the template swagger. After deployment, I tested with a Node.js project by the npm module aws-api-gateway-client.
It works well with: get bucket lists, get bucket info, get one item, put a bucket, put a plain text object, however I am blocked with put a binary file.
firstly, I ensure ACL is allowed with all permissions on S3. secondly, binary support also added
image/gif
application/octet-stream
The code snippet is as below. The behaviors are:
1) after invokeAPI, the callback function is never hit, after sometime, the Node.js project did not respond. no any error message. The file size (such as an image) is very small.
2) with only two times, the uploading seemed to work, but the result file size is bigger (around 2M bigger) than the original file, so the file is corrupt.
Could you help me out? Thank you!
var filepathname = './items/';
var filename = 'image1.png';
fs.stat(filepathname+filename, function (err, stats) {
var fileSize = stats.size ;
fs.readFile(filepathname+filename,'binary',function(err,data){
var len = data.length;
console.log('file len' + len);
var pathTemplate = '/my-test-bucket/' +filename ;
var method = 'PUT';
var params = {
folder: '',
item:''
};
var additionalParams = {
headers: {
'Content-Type': 'application/octet-stream',
//'Content-Type': 'image/gif',
'Content-Length': len
}
};
var result1 = apigClient.invokeApi(params,pathTemplate,method,additionalParams,data)
.then(function(result){
//never hit :(
console.log(result);
}).catch( function(result){
//never hit :(
console.log(result);
});;
});
});
We encountered the same problem. API Gateway is meant for limited data (10MB as of now), limits shown here,
http://docs.aws.amazon.com/apigateway/latest/developerguide/limits.html
Self Signed URL to S3:
Create an S3 self signed URL for POST from the lambda or the endpoint where you are trying to post.
How do I put object to amazon s3 using presigned url?
Now POST the image directly to S3.
Presigned POST:
Apart from posting the image if you want to post additional properties, you can post it in multi-form format as well.
http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#createPresignedPost-property
If you want to process the file after delivering to S3, you can create a trigger from S3 upon creation and process with your Lambda or anypoint that need to process.
Hope it helps.

ringojs fileupload example

Does anyone have an example of uploading a file to the server using ringojs?
There's a simple upload example in the demo app, but it stores uploads in-memory which is not a good idea for most apps. To save uploads to a temporary file you'll currently have to do something like this (this is a modified version of the upload demo action):
var fu = require("ringo/webapp/fileupload");
function upload(req) {
if (fu.isFileUpload(req.contentType)) {
var params = {};
fu.parseFileUpload(req, params, req.charset, fu.TempFileFactory);
return {
status: 200,
headers: {"Content-Type": "text/plain"},
body: [params.file.name, " saved to ", params.file.tempfile]
};
}
return Response.skin(module.resolve('skins/upload.txt'), {
title: "File Upload"
});
}
Unfortunately, there was a bug with saving uploads to temp files that I just fixed, so you'll have to use a current git snapshot or patch file modules/ringo/webapp/fileupload.js manually:
http://github.com/ringo/ringojs/commit/1793a815a9ca3ffde4aa5a07c656456969b504f9
We also need some high level way of doing this for the next release (e.g. setting a req.uploadTempDir property). I'll open an issue for this.