Query in Azure function stop working after a few time deploy? - azure

I'm just start using azure functions. Follow the instructions here, i modified the code & deploy it to my function
[FunctionName("Function1")]
public static async Task<HttpResponseMessage> Run([HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)]HttpRequestMessage req, TraceWriter log)
{
log.Info("C# HTTP trigger function processed a request.");
// parse query parameter
string name = req.GetQueryNameValuePairs()
.FirstOrDefault(q => string.Compare(q.Key, "name", true) == 0)
.Value;
if (name == null)
{
// Get request body
dynamic data = await req.Content.ReadAsAsync<object>();
name = data?.name;
}
return name == null
? req.CreateResponse(HttpStatusCode.BadRequest, "Please pass a name on the query string or in the request body")
: req.CreateResponse(HttpStatusCode.OK, "Hello " + Multiply().ToString());
}
Combine with my code
public static int Multipy() {
Random rnd = new Random();
return rnd.Next(1, 10)*rnd.Next(1, 10);
}
The function run successfully when deploy, but after a few times rebuild & deploy again, this show up
enter image description here
Remove name query & it work as usual
enter image description here
Is there something wrong with my code or Azure has limitation for deploy function? How may i fix this?

Isn't it problem with a query symbol? it is already ? used so another param should be joined with & sign
{url}?code={someCode}&name={name}

Related

how to use basic authentication on azure functions ISOLATED?

how do i get the user and password informed in basic authentication in azure functions ISOLATED?
exemple, using the app SOAPUI to make a call to the function:
[https://i.imgur.com/3u7eymT.png]
how do i get in the function this USER and his password ?
[Function("Function1")]
public HttpResponseData Run([HttpTrigger(AuthorizationLevel.Function, "get", "post")] HttpRequestData req)
{
_logger.LogInformation("C# HTTP trigger function processed a request.");
var response = req.CreateResponse(HttpStatusCode.OK);
response.Headers.Add("Content-Type", "text/plain; charset=utf-8");
response.WriteString("Welcome to Azure Functions!");
return response;
}
i also have a middleware how i get this info in him too?
public async Task Invoke(FunctionContext context, FunctionExecutionDelegate next)
{
i tried to search in the header, or the identities but i can't find this info/login and password
For Basic Authentication we need to change the open API security property values as below
[OpenApiSecurity("basic_auth", SecuritySchemeType.Http, Scheme = OpenApiSecuritySchemeType.Basic)]
Below is the screenshot of SoapUI
Authorization header need to be added in SoapUI as shown below
Code In Function
var headers = req.Headers["Authorization"];
if (ValidateToken(headers))
{
string name = req.Query["name"];
string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
dynamic data = JsonConvert.DeserializeObject(requestBody);
name = name ?? data?.name;
string responseMessage = string.IsNullOrEmpty(name) ? "Pass a name in the query string" : $"{name}";
return new OkObjectResult(responseMessage);
}
Validation Code part
string encode_Credentials = header.Substring("Basic ".Length).Trim();
Encoding encode = Encoding.GetEncoding("iso-8859-1");
string credentials = encode.GetString(Convert.FromBase64String(encode_Credentials));
int seperatorIndex = credentials.IndexOf(':');
var username = credentials.Substring(0, seperatorIndex);
var password = credentials.Substring(seperatorIndex + 1);
if (username is "Rajesh" && password is "1142") return true;
else return false;

Trigger notification after Computer Vision OCR extraction is complete

I am exploring Microsoft Computer Vision's Read API (asyncBatchAnalyze) for extracting text from images. I found some sample code on Microsoft site to extract text from images asynchronously.It works in following way:
1) Submit image to asyncBatchAnalyze API.
2) This API accepts the request and returns a URI.
3) We need to poll this URI to get the extracted data.
Is there any way in which we can trigger some notification (like publishing an notification in AWS SQS or similar service) when asyncBatchAnalyze is done with image analysis?
public class MicrosoftOCRAsyncReadText {
private static final String SUBSCRIPTION_KEY = “key”;
private static final String ENDPOINT = "https://computervision.cognitiveservices.azure.com";
private static final String URI_BASE = ENDPOINT + "/vision/v2.1/read/core/asyncBatchAnalyze";
public static void main(String[] args) {
CloseableHttpClient httpTextClient = HttpClientBuilder.create().build();
CloseableHttpClient httpResultClient = HttpClientBuilder.create().build();;
try {
URIBuilder builder = new URIBuilder(URI_BASE);
URI uri = builder.build();
HttpPost request = new HttpPost(uri);
request.setHeader("Content-Type", "application/octet-stream");
request.setHeader("Ocp-Apim-Subscription-Key", SUBSCRIPTION_KEY);
String image = "/Users/xxxxx/Documents/img1.jpg";
File file = new File(image);
FileEntity reqEntity = new FileEntity(file);
request.setEntity(reqEntity);
HttpResponse response = httpTextClient.execute(request);
if (response.getStatusLine().getStatusCode() != 202) {
HttpEntity entity = response.getEntity();
String jsonString = EntityUtils.toString(entity);
JSONObject json = new JSONObject(jsonString);
System.out.println("Error:\n");
System.out.println(json.toString(2));
return;
}
String operationLocation = null;
Header[] responseHeaders = response.getAllHeaders();
for (Header header : responseHeaders) {
if (header.getName().equals("Operation-Location")) {
operationLocation = header.getValue();
break;
}
}
if (operationLocation == null) {
System.out.println("\nError retrieving Operation-Location.\nExiting.");
System.exit(1);
}
/* Wait for asyncBatchAnalyze to complete. In place of this wait, can we trigger any notification from Computer Vision when the extract text operation is complete?
*/
Thread.sleep(5000);
// Call the second REST API method and get the response.
HttpGet resultRequest = new HttpGet(operationLocation);
resultRequest.setHeader("Ocp-Apim-Subscription-Key", SUBSCRIPTION_KEY);
HttpResponse resultResponse = httpResultClient.execute(resultRequest);
HttpEntity responseEntity = resultResponse.getEntity();
if (responseEntity != null) {
String jsonString = EntityUtils.toString(responseEntity);
JSONObject json = new JSONObject(jsonString);
System.out.println(json.toString(2));
}
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
There is no notification / webhook mechanism on those asynchronous operations.
The only thing that I can see right know is to change the implementation you mentioned by using a while condition which is checking regularly if the result is there or not (and a mechanism to cancel waiting - based on maximum waiting time or number of retries).
See sample in Microsoft docs here, especially this part:
// If the first REST API method completes successfully, the second
// REST API method retrieves the text written in the image.
//
// Note: The response may not be immediately available. Text
// recognition is an asynchronous operation that can take a variable
// amount of time depending on the length of the text.
// You may need to wait or retry this operation.
//
// This example checks once per second for ten seconds.
string contentString;
int i = 0;
do
{
System.Threading.Thread.Sleep(1000);
response = await client.GetAsync(operationLocation);
contentString = await response.Content.ReadAsStringAsync();
++i;
}
while (i < 10 && contentString.IndexOf("\"status\":\"Succeeded\"") == -1);
if (i == 10 && contentString.IndexOf("\"status\":\"Succeeded\"") == -1)
{
Console.WriteLine("\nTimeout error.\n");
return;
}
// Display the JSON response.
Console.WriteLine("\nResponse:\n\n{0}\n",
JToken.Parse(contentString).ToString());

Azure Function Status Code 500 internal server error

I have a logic app that uses azure function as a http trigger and gets a return string.
When the azure function is to receive a Base64 string, create a file with the information and uploads to the assigned storage account, I keep getting status code 500 internal server error from the Azure function every time I run it. After many trial and error I deduced the problem occurs from when the file is to be created from the Base64 string and when the blob container client is created.
So Help me Please.
UPDATE: As per some of your suggestions, I implemented application insights ran it a few times and got this error occuring twice:
Azure.RequestFailedException
Message: Exception while executing function: BlobAdd The specifed resource name contains invalid characters
Status: 400 (The specifed resource name contains invalid characters.)
ErrorCode: InvalidResourceName
FailedMethod: Azure.Storage.Blobs.BlobRestClient+Container.CreateAsync_CreateResponse.
public static async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
ILogger log)
{
log.LogInformation("C# HTTP trigger function processed a request.");
string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
return await Base64(requestBody);
}
public static async Task<IActionResult> Base64(string Base64Body)
{
string HoldDBase = "";
string TestBlobData = "null";
if (Base64Body.Length > 10)
{
HoldDBase = Base64Body;
}
else
{
TestBlobData = "The Base64Body did not Pass";
return (ActionResult)new OkObjectResult
(
new
{
TestBlobData
}
);
}
//Connection string of the Storage Account Azure
string ConnectionString = "xxxxxxxxx";
// Create a BlobServiceClient object which will be used to create a container client
BlobServiceClient blobServiceClient = new BlobServiceClient(ConnectionString);
//Create a unique name of the container
string ContainerName = "Base64_Blob" + Guid.NewGuid().ToString();
//create the container and return a container client Object
BlobContainerClient ContainerClient = await blobServiceClient.CreateBlobContainerAsync(ContainerName); //Problem Here
//create a local file in the Storage
string localPath = "D:/Reliance/OlaForm/uploadsO";
string fileName = "quickstart" + Guid.NewGuid().ToString() + ".txt";
string localFilePath = Path.Combine(localPath, fileName);
//convert string to bytes
byte[] BaseBytes = Convert.FromBase64String(HoldDBase);
//create file in local data
await File.WriteAllBytesAsync(localFilePath,BaseBytes); //Problem Here
//get reference to a blob
BlobClient blobclient = ContainerClient.GetBlobClient(fileName);
// Open the file and upload its data
FileStream uploadFileStream = File.OpenRead(localFilePath);
await blobclient.UploadAsync(uploadFileStream);
// blobclient.Upload(uploadFileStream);
uploadFileStream.Close();
//blob id from blobclient and return it
TestBlobData = blobclient.ToString();
TestBlobData = HoldDBase;
return (ActionResult)new OkObjectResult
(
new {
TestBlobData
}
);
}
You are trying to write to the "D" disk. Since the Azure function does not have direct access to disks, you get a 500 error when trying to write to a disk that does not exist.
To write to a file from an Azure function you can use the Azure Storage SDK.

MD5 value of upload file

I'm trying to extract MD5 and length (size) of the upload blob using Azure function using Http Trigger, Below the code im experimenting, but I always get null and -1. Please someone confirm the code is correct or any other option is available
public static async Task<IActionResult> Run(HttpRequest req,string inputBlob, ILogger log)
{
log.LogInformation("C# HTTP trigger function processed a request.");
string name = req.Query["name"];
log.LogInformation($"name,{inputBlob}");
log.LogInformation("Blob content: " + inputBlob.Properties.Length); //This is printing content of blob
CloudBlockBlob blob;
var credentials = new StorageCredentials("xxx", "xxxx");
var client = new CloudBlobClient(new Uri("https://xxx.blob.core.windows.net"), credentials);
var container = client.GetContainerReference("parent");
blob = container.GetBlockBlobReference("file.csv");
log.LogInformation("Blob details: " + blob.Properties.Length); //This is printing -1, if i provide ContentMD5 its showing null. Bascially its not able to read the blob
string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
dynamic data = JsonConvert.DeserializeObject(requestBody);
name = name ?? data?.name;
return name != null
? (ActionResult)new OkObjectResult($"Hello, {name}")
: new BadRequestObjectResult("Please pass a name on the query string or in the request body");
}
You are missing FetchAttributesAsync() (or FetchAttributes()) method before you try to retrieve any properties of the blob.
//your other code
blob = container.GetBlockBlobReference("file.csv");
blob.FetchAttributesAsync()(); //or FetchAttributes()
//then you can try to get any property here.

How to call PUT method from Web Api using HttpClient?

I want to call Api function (1st) . from 2nd Api function using HttpClient. But I always get 404 Error.
1st Api Function (EndPoint : http : // localhost : xxxxx /api/Test/)
public HttpResponseMessage Put(int id, int accountId, byte[] content)
[...]
2nd Api function
public HttpResponseMessage Put(int id, int aid, byte[] filecontent)
{
WebRequestHandler handler = new WebRequestHandler()
{
AllowAutoRedirect = false,
UseProxy = false
};
using (HttpClient client = new HttpClient(handler))
{
client.BaseAddress = new Uri("http://localhost:xxxxx/");
// Add an Accept header for JSON format.
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var param = new object[6];
param[0] = id;
param[1] = "/";
param[2] = "?aid=";
param[3] = aid;
param[4] = "&content=";
param[5] = filecontent;
using (HttpResponseMessage response = client.PutAsJsonAsync("api/Test/", param).Result)
{
return response.EnsureSuccessStatusCode();
}
}
}
So My question is that. Can I post Method Parameter as an object array from HttpClient as I did ? I don't want to Pass model as method parameter.
What is the wrong in my code ?
Unable to get any response , after change code to
return client.PutAsJsonAsync(uri, filecontent)
.ContinueWith<HttpResponseMessage>
(
task => task.Result.EnsureSuccessStatusCode()
);
OR
return client.PutAsJsonAsync(uri, filecontent)
.ContinueWith
(
task => task.Result.EnsureSuccessStatusCode()
);
As you probably found out, no you can't. When you call PostAsJsonAsync, the code will convert the parameter to JSON and send it in the request body. Your parameter is a JSON array which will look something like the array below:
[1,"/","?aid",345,"&content=","aGVsbG8gd29ybGQ="]
Which isn't what the first function is expecting (at least that's what I imagine, since you haven't showed the route info). There are a couple of problems here:
By default, parameters of type byte[] (reference types) are passed in the body of the request, not in the URI (unless you explicitly tag the parameter with the [FromUri] attribute).
The other parameters (again, based on my guess about your route) need to be part of the URI, not the body.
The code would look something like this:
var uri = "api/Test/" + id + "/?aid=" + aid;
using (HttpResponseMessage response = client.PutAsJsonAsync(uri, filecontent).Result)
{
return response.EnsureSuccessStatusCode();
}
Now, there's another potential issue with the code above. It's waiting on the network response (that's what happens when you access the .Result property in the Task<HttpResponseMessage> returned by PostAsJsonAsync. Depending on the environment, the worse that can happen is that it may deadlock (waiting on a thread in which the network response will arrive). In the best case this thread will be blocked for the duration of the network call, which is also bad. Consider using the asynchronous mode (awaiting the result, returning a Task<T> in your action) instead, like in the example below
public async Task<HttpResponseMessage> Put(int id, int aid, byte[] filecontent)
{
// ...
var uri = "api/Test/" + id + "/?aid=" + aid;
HttpResponseMessage response = await client.PutAsJsonAsync(uri, filecontent);
return response.EnsureSuccessStatusCode();
}
Or without the async / await keywords:
public Task<HttpResponseMessage> Put(int id, int aid, byte[] filecontent)
{
// ...
var uri = "api/Test/" + id + "/?aid=" + aid;
return client.PutAsJsonAsync(uri, filecontent).ContinueWith<HttpResponseMessage>(
task => task.Result.EnsureSuccessStatusCode());
}

Resources