I have an azure function that returns an image of my top blog from my feed. Now I have just added that function URL as the image src as below in the Readme.md file.
<img src="https://getlatestposts.azurewebsites.net/api/GetLatestPosts?code=VS4fy5DNxpj8/SUS0Chp0aGBux36c9OyOg5KhmSjh5dPVBvCaVaEuA==">
But the image is not loading at all, and when I check the HTML generated, I could see that the src is been updated with some weird URL from "https://camo.githubusercontent.com". There is also an additional a tag introduced.
Anyone else faced this issue?
Finally, I was able to fix this issue. What I did is that, I returned a File Stream from my Azure Function, instead of returning a base64 string. Below is my Azure function.
[FunctionName("GetLatestPosts")]
public static FileStreamResult Run([HttpTrigger(AuthorizationLevel.Function, "get", Route = null)] HttpRequest request, ILogger log) {
try {
var baseString = WriteOnImage(GetLatestFeeds());
// Had to do this, as it was throwing error "The input is not a valid Base-64 string as it contains a non-base 64 character"
string convert = baseString.Replace("data:image/png;base64,", String.Empty);
var bytes = Convert.FromBase64String(convert);
var result = new FileStreamResult(new MemoryStream(bytes), Configuration.ContentType);
log.LogInformation("Returning stream now!");
request.HttpContext.Response.Headers.Add("Cache-Control", "s-maxage=1, stale-while-revalidate");
return result;;
} catch (System.Exception ex) {
log.LogError($ "Something went wrong: {ex}");
throw ex;
}
}
I did write an article about this entire application, you can read it here. It contains the GitHub repositories too, just in case, if you are interested.
Related
To simplify the problem let's say I have a simple asp.net mvc endpoint which receives a file. In most of the cases it will be a .jpg one:
[HttpPost]
[Route("appraisal/{appraisalID}/files/{fileSubjectCode}")]
[ProducesResponseType(StatusCodes.Status201Created, Type = typeof(IEnumerable<AppraisalFileModel>))]
[ProducesResponseType(StatusCodes.Status400BadRequest, Type = typeof(ModelStateDictionary))]
public async Task<IActionResult> UploadAppraisalFile(int appraisalID, string fileSubjectCode, [FromForm]IFormFile file)
{
file = file ?? Request.Form.Files?.FirstOrDefault();
// intermitent code change to investigate and validate Complete File Size and Actual File Size
var completeFileSizeHeader = Request.Headers["Complete-File-Size"];
int.TryParse(completeFileSizeHeader, out int completeFileSize);
if (file == null || file.Length != completeFileSize)
{
using (var stream = new MemoryStream())
{
await file.CopyToAsync(stream);
stream.Position = 0;
var inputAsString = Convert.ToBase64String(stream.ToArray());
Logger.LogDebug("Complete-File-Size header doesn't much received byteArray size", file.Length, completeFileSize, inputAsString);
}
return StatusCode(StatusCodes.Status411LengthRequired, "Complete-File-Size header doesn't much received byteArray size");
}
// some other logic..
}
I'm trying to prevent an edge case when somebody performs a POST request against my API UploadAppraisalFile endpoint and suddenly loses an internet connection which would result in sending a request with not the full file content.
My idea was to count the file size at the point where the file is uploaded, add the information about the file size as an extra HTTP-HEADER (I called it Complete-File-Size), and then when the request reaches the backend, count if the received file size is exactly the same as the Complete-File-Size.
To produce such an issue/edge case I tried:
uploading a big file(about 16MB) and then suddenly after submitting the HTML form immediately close the browser window.
uploading a file and then, in the Chrome browser, in the Network pane, change the uploading speed to a very minimum, then submit the form and then immediately close the browser.
When I run the debug mode, in each case I found that either: UploadAppraisalFile endpoint was never reached or if it was reached then always the full file was sent. For the 2nd successful case, to be 100% sure I converted the received file into base64 string and then I checked how the file looks like in https://codebeautify.org/base64-to-image-converter.
My question is: Is it even possible that the sent POST request is broken and contains not full file content due to a broken internet connection that happened suddenly during the sending process? If yes, then what's the best way to produce the issue. Cheers
You can pass HttpContext.RequestAborted as a CancellationToken to ALL async methods provided by .NET in "some other logic" part.
Let's use code you provided as an example :
await stream.CopyToAsync(memoryStream, HttpContext.RequestAborted)
I don't have an access to a full method but I assume you save it to some blob storage or file system. Most of these persistence API's accept CancellationToken as a parameter.
Receiving incomplete file
I was able to achieve a "partial" file using this code and Postman. It will basically read chunks from response stream until connection is interrupted.
As soon as I close Postman window TaskCancelledException is raised and stream is closed.
[HttpPost]
public async Task<IActionResult> UploadAppraisalFile([FromForm] IFormFile file)
{
var appraisalfile = file ?? Request.Form.Files.FirstOrDefault();
if (appraisalfile != null)
{
var buffer = ArrayPool<byte>.Shared.Rent(1024);
using var stream = appraisalfile.OpenReadStream();
while (await stream.ReadAsync(buffer, 0, buffer.Length, HttpContext.RequestAborted) > 0)
{
// Do something with buffer
_logger.LogInformation("Total length (bytes) {0}, partial length (bytes) {1}", stream.Length, stream.Position);
}
ArrayPool<byte>.Shared.Return(buffer);
}
return Ok();
}
I want to return a file via a route that I don't want public. My users will need to use a URL with a unique and one time code. Because of that I don't want to use the public folder via the FileMiddleware.
This is a binary executable, not a text file. I can grab the file as data with FileManager, but it seems like Future<Data> is not a valid return type for a route.
After searching StackOverflow, the only thing I've found is this reply to a similar question: How do I download a file and send a file using Vapor server side swift?
But that doesn't really fill in much on HOW to accomplish it.
router.get("customfile") { req -> Future<Response> in
return try req.streamFile(at: "/path/to/file")
}
This works for me.
func routes(_ app: Application) throws {
app.get("downloadthefile") { req -> Response in
let filePath = "path/to/the/file"
let result = req.fileio.streamFile(at: filePath)
return result
}
}
I am trying to convert WikiMarkup data to Confluence's XHTML based format. I saw there are 2 different ways to do the same.
1) Use the rest/XML Rpc based API convertWikiToStorageFormat(String token, String markup) to do the same.
2) Other way is to use WikiToXhtmlMigrator to do the same Task. Since I am using Confluence SDK, I choose 2nd way to do the same.
public String getXHTMLConvertedTextFromWiki(String markupData){
String content = null;
try {
RenderContext renderContext = new RenderContext();
DefaultConversionContext defaultConversionContext = new DefaultConversionContext(renderContext);
ExceptionTolerantMigrator wikiToXhtmlMigrator = (ExceptionTolerantMigrator) ContainerManager.getComponent("wikiToXhtmlMigrator");
content = wikiToXhtmlMigrator.migrate(markupData, defaultConversionContext).getContent();
}catch(Exception e){
e.printStackTrace();
}
return content;
}
But Always, I am getting the exception:
[INFO] [talledLocalContainer] java.lang.NullPointerException
[INFO] [talledLocalContainer] at com.atlassian.confluence.content.render.xhtml.migration.WikiToXhtmlMigrator.migrate(WikiToXhtmlMigrator.java:57)
[INFO] [talledLocalContainer] at com.atlassian.confluence.content.render.xhtml.migration.WikiToXhtmlMigrator.migrate(WikiToXhtmlMigrator.java:69)
I tried to push the render mode by setting All in render Context but got the same exception.
renderContext.pushRenderMode(RenderMode.ALL);
Please let me know the what is the problem in this example and show the correct way to do it.
Able to convert markup to Xhtml through below code.
public String getXHTMLConvertedTextFromWiki(String wikiText){
String content = null;
try {
List<RuntimeException> exceptions = newArrayList();
XhtmlContent xhtmlContent = (XhtmlContent)ContainerManager.getComponent("xhtmlContent");
content = xhtmlContent.convertWikiToStorage(wikiText, new DefaultConversionContext(new PageContext()),exceptions);
for(RuntimeException e : exceptions){
log.error(e.getMessage());
}
}catch(Exception e){
e.printStackTrace();
}
return content;
}
Please make sure that, your newline characters should not be lost while reading Page Markup Data if reading from external source.
This is regarding Sendgrid incoming mail webhook, I have referred this URL SendGrid incoming mail webhook - how do I secure my endpoint, and got some idea how to go about this, but, as I am new to MVC / WebAPI, could anyone give me the controller method code snippet to catch the JSON format HTTP post and save to my application folder.
This is the solution I found after googling and with slight modifications:
[HttpPost, HttpGet]
[EnableCors(origins: "*", headers: "*", methods: "*")]
public async Task Post()
{
if (Request.Content.IsMimeMultipartContent("form-data"))
try
{
//To get complete post in a string use the below line, not used here
string strCompletePost = await Request.Content.ReadAsStringAsync();
HttpContext context = HttpContext.Current;
string strFrom = context.Request.Form.GetValues("from")[0];
string strEmailText = context.Request.Form.GetValues("email")[0];
string strSubject = context.Request.Form.GetValues("subject")[0];
//Not useful I guess, because it always return sendgrid IP
string strSenderIP = context.Request.Form.GetValues("sender_ip")[0];
}
catch (Exception ex)
{
}
}
I tried, retrieving the values as
String to = context.Request.Params["to"];
but, the value returned is not consistent, i.e. most of the times it is returning null and occasionally returns actual value stored in it.
If anyone have a better solution, please let me know.
Thank you
If for some reason ["to"] doesn't work for you, try to get ["envelope"] value,
context.Request.Form.GetValues("envelope")[0]
which looks like
{"to":["emailto#example.com"],"from":"emailfrom#example.com"}
I am writing a file service using Asp.Net’s Web Api. The service retrieves files (Css, Excel, Csv, etc.) from SQL Server and serves them up in response to Get requests.
My first test case is for Css files. The issue is that, while I can see the correct data on the server side, when the browser retrieves/decodes it, the results are mangled. The issue appears to be related to the encodings.
Here are the request/response headers in FireFox:
When I click on the response tab in FireBug, here’s what it looks like:
The results look like ascii being displayed as utf8. This is the html view in FireBug:
The above example is an iFrame inside a Facebook application which is running ssl.
If I take the url and open it directly in the browser, it works and correctly displays my Css:
In summary, when I retrieve my Css file from a tag inside my Facebook app, I get garbage (encoding issue?). If I retrieve it straight from the browser, it works.
My CssFormatter MediaTypeFormatter code:
public override Task WriteToStreamAsync(Type type, object value, Stream writeStream, HttpContent content, TransportContext transportContext)
{
var taskSource = new TaskCompletionSource<object>();
try
{
var incomingFile = value as FileRestService.Entity.IFile;
var ms = new MemoryStream(incomingFile.DataBuffer);
ms.CopyTo(writeStream);
ms.Flush();
taskSource.SetResult(writeStream);
}
catch (Exception e)
{
taskSource.SetException(e);
}
return taskSource.Task;
}
Am I creating the response stream incorrectly? I noticed that the response headers do not specify the encoding. Is this an issue?
I find the easiest way to handle this is to write something along the lines of (here's the important details):
public class Formatter : MediaTypeFormatter {
// TODO override the constructor to add some mappings or some other way for this formatter to be picked up
// TODO override CanReadType and CanWriteType according to your rules
public override void SetDefaultContentHeaders(Type t, HttpContentHeaders headers, string mediaType) {
base.SetDefaultContentHeaders(t, headers, mediaType);
headers.ContentDisposition = new ContentDispositionHeaderValue("attachment") {
FileName = "SomeName.ext"
};
}
public override Task WriteToStreamAsync(Type t, object value, Stream s, HttpContentHeaders headers, TransportContext context) {
return Task.Factory.StartNew(() => {
// TODO code to write to the output stream, flush it but don't explicitly close it
});
}
}