Creating a Linkedin image ugcPost works when posting from localhost but not from AWS ECS - linkedin

I am creating image shares on company profiles in my java app following the docs here --->https://learn.microsoft.com/en-us/linkedin/consumer/integrations/self-serve/share-on-linkedin#create-an-image-share
The problem that I'm encountering is that after uploading the file successfully(I get 201), from AWS ECS FARGATE container,but posting is successful from localhost. this is my code below:
String mediaUploadResponse = registerMediaUpload(userId, headers);
JsonNode mediaUpload = objectMapper.readTree(mediaUploadResponse);
String uploadUrl = mediaUpload.findPath("uploadUrl").asText();
HttpClient client = HttpClientBuilder.create().build();
HttpPut request = new HttpPut(uploadUrl);
request.addHeader("Content-Type", APPLICATION_OCTET_STREAM_VALUE);
request.setHeader("X-Restli-Protocol-Version", "2.0.0");
request.setHeader("Authorization", requireNonNull(headers.get(AUTHORIZATION)).get(0));
Path tempFilePath = Files.createTempFile("linkedin", null);
try (InputStream fileStream = new URL(fileUrl).openStream()) {
Files.write(tempFilePath, fileStream.readAllBytes());
File tempFile = tempFilePath.toFile();
request.setEntity(new FileEntity(tempFile, IMAGE_PNG));
HttpResponse response = client.execute(request);
if (response.getStatusLine().getStatusCode() == 201) {
log.info("------------------- media upload result {}", response.getEntity());
return mediaUpload;
} else {
log.error("linkedin media upload request failed {}", request);
throw new BadRequestException(response.toString());
}
} finally {
boolean deleted = tempFilePath.toFile().delete();
log.info("------------------- tempfile deleted: {}", deleted);
}
mediaUpload is the result received from registering the media upload by calling POST https://api.linkedin.com/v2/assets?action=registerUpload
I'm checking the asset status using /v2/assets/{asset-id} and I ultimately get:
{
"recipes": [
{
"recipe": "urn:li:digitalmediaRecipe:feedshare-image",
"status": "CLIENT_ERROR"
}
],
"serviceRelationships": [
{
"relationshipType": "OWNER",
"identifier": "urn:li:userGeneratedContent"
}
],
"mediaTypeFamily": "STILLIMAGE",
"created": 1588963432407,
"id": "C4D22AQGIhdXwlSvDZQ",
"lastModified": 1588963433173,
"status": "ALLOWED"
}
But when running from localhost everything works as expected and post shows up on company feed.
Really struggling to understand what could be the issue.

I actually managed to solve the issue in the meantime. And the issue was caused by the fact that fileUrl was a link to an file in a s3 bucket linked as an origin to a cloudfront deployment to which I had direct access. So I used the AmazonS3 s3client to get the inputstream directly.

Related

cloud run api service response broken when I use firebase rewrites

The firebase Sveltekit client app and server api use a google cloud run hosting container. This works fine when I use the cloud run url: https://app...-4ysldefc4nq-uc.a.run.app/
But when I use firebase rewriting the client works fine using: https://vc-ticker.web.app/... but receives 502 and 504 responses from the API service. The cloud run log does not show any errors, receives the client fetch POST request and returns a Readablestream response.
But this API service response stream never arrives when using rewrites.
firebase.json
{
"hosting": {
"public": "public", !! NOT used, cloud run hosts the app
"ignore": [
"firebase.json",
"**/.*",
"**/node_modules/**"
],
"rewrites": [
{
"source": "**",
"run": {
"serviceId": "vc-ticker-app",
"region": "us-central1"
}
}
]
}
}
+page.svelte client API request:
const logging = true;
const controller = new AbortController();
let reader = null;
const signal = controller.signal;
async function streamer(params) {
console.log("stream with logging:", logging, JSON.stringify(params));
try {
const response = await fetch("api/my-ticker", {
method: "POST",
body: JSON.stringify(params),
headers: {
"content-type": "application/json",
},
signal: signal,
});
const stream = response.body.pipeThrough(new TextDecoderStream("utf-8"));
reader = stream.getReader();
while (true) {
const { value, done } = await reader.read();
if (done || response.status !== 200) {
console.log("done response", response.status, done, value);
await reader.cancel(`reader done or invalid response: ${response.status}`);
reader = null;
break;
}
// response ok: parse multi json chunks => array => set store
const quotes = {};
JSON.parse(`[${value.replaceAll("}{", "},{")}]`).forEach((each, idx) => {
quotes[each.id] = [each.price, each.changePercent];
console.log(`quote-${idx}:`, quotes[each.id]);
});
positions.set(quotes);
}
} catch (err) {
console.log("streamer exception", err.name, err);
if (reader) {
await reader.cancel(`client exception: ${err.name}`);
reader = null;
}
}
}
$: if ($portfolio?.coins) {
const params = {
logging,
symbols: Object.values($portfolio.symbols),
};
streamer(params);
}
onDestroy(async () => {
if (reader) await reader.cancel("client destroyed");
controller.abort();
console.log("finished");
});
I use the Sveltekit adapter-node to build the app.
With rewrite rules, you can direct requests that match specific patterns to a single destination.Check your firebase.json file and verify if the rewrite configuration in the hosting section has the redirect serviceId name same as that from the deployed container image,as per below example
"hosting": {// ...
// Add the "rewrites" attribute within "hosting"
"rewrites": [ {
"source": "/helloworld",
"run": {
"serviceId": "helloworld", // "service name" (from when you [deployed the container image][3])
"region": "us-central1" // optional (if omitted, default is us-central1)
}
} ]
}
It is important to note that Firebase Hosting is subject to a 60-second request timeout. If your app requires more than 60 seconds to run, you'll receive an HTTPS status code 504 (request timeout). To support dynamic content that requires longer compute time, consider using an App Engine flexible environment.
You should also check the Hosting configuration page for more details about rewrite rules. You can also learn about the priority order of responses for various Hosting configurations.
I made it work with an external link to the cloud run api service (cors).
But I still do not understand why It can't be done without cors using only firebase rewrites.
+page.svelte client API request update:
Now using GET and an auth token to verify the api request on the endpoint server
const search = new URLSearchParams(params);
const apiHost = "https://fs-por....-app-4y...q-uc.a.run.app/api/yahoo-finance-streamer";
const response = await fetch(`${apiHost}?${search.toString()}`, {
method: "GET",
headers: {
"auth-token": await getIdToken(),
},
signal: signal,
});
And a handle hook to verify the auth token and handle cors:
const logging = true;
const reqUnauthorized = { status: 403, statusText: 'Unauthorized!' };
/** #type {import('#sveltejs/kit').Handle} */
export async function handle({ event, resolve }) {
let response;
if (event.request.method !== "OPTIONS") {
if (event.url.pathname.startsWith('/api')) {
const authToken = event.request.headers.get("auth-token")
const { error = null, decodedToken } = await decodeIdToken(logging, authToken)
if (error) return new Response(error.message, reqUnauthorized);
if (verifyUser(logging, decodedToken) === false) {
return new Response(`user auth failed for: ${decodedToken.email}`, reqUnauthorized);
}
}
response = await resolve(event);
} else { // handle cors preflight OPTIONS
response = new Response("", { status: 200 });
}
response.headers.append('Access-Control-Allow-Headers', "*");
response.headers.append('Access-Control-Allow-Origin', "*");
return response;
}
From firebase support:
I got an answer from the engineering team. Unfortunately Firebase Hosting does not support streaming responses at the moment. I’ve created a feature request so they will consider implementing it.
Please be informed that submitting a feature request doesn’t guarantee that it will be implemented. Keep an eye on the release notes.
I realize that this is not the answer you expected from me, but unfortunately there is nothing I can do about it.

XRay-Import json result file with Cloud Rest API call getting error "No project could be found with key 'null'."

We are trying to import test execution result in json format to xray Jira cloud by cloud Rest API call. After importing through Rest API call we are getting below error.
I gone through the solutions but couldn't got working solution.
{"error": "Error retrieving Project from Jira with key "null": No project could be found with key 'null'."}
Below is my code snippet:
public void postAPICall(){
File dataFile = new File("src/main/resources/Payloads/auth.json");
String url ="https://xray.cloud.getxray.app/api/v2/authenticate";
RequestSpecification request = RestAssured.given();
request.header("Content-Type", "application/json");
request.body(dataFile);
Response response = request.post(url);
ResponseBody body = response.getBody();
tokenResult=body.asString();
}
#Test
public void postCallUpdateTestResult(){
postAPICall();
File jsonDataInFile = new File("src/main/resources/Payloads/SimpleExecutionResult.json");
String url ="https://xray.cloud.getxray.app/api/v2/import/execution?testExecKey=XX-XX";
RequestSpecification request = RestAssured.given();
request.header("Content-Type", "application/json");
request.header("Authorization", "Bearer "+tokenResult.substring(1,(tokenResult.length()-1)));
request.body(jsonDataInFile);
Response response = request.post(url);
ResponseBody body = response.getBody();
System.out.println(body.asString());
}
auth.json
{
"client_id": "XXXXXXXXXXXXXXXXXX",
"client_secret": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
}
SimpleExecutionResult.json
{
"testExecutionKey": "XX-XX",
"tests": [
{
"testKey": "XX-XX",
"status": "FAILED"
},
{
"testKey": "XX-XX",
"status": "PASSED"
}
]
}

FirebaseAdmin messaging returning 404 not found

I am writing an API that sends an firebase message (using the official FirebaseAdmin library) when requested to a android device. I got it working perfect in normal C#, but in ASP.NET core I always get a 404 not found exception.
Response status code does not indicate success: 404 (NotFound)
{
"error": {
"code": 404,
"message": "Requested entity was not found.",
"errors": [
{
"message": "Requested entity was not found.",
"domain": "global",
"reason": "notFound"
}
],
"status": "NOT_FOUND"
}
}
I run the following code at startup:
if (FirebaseApp.DefaultInstance == null)
{
FirebaseApp.Create(new AppOptions
{
Credential = GoogleCredential.FromFile($#"{env.WebRootPath}\app-5a821-firebase-adminsdk-pf36f-6f44114d87.json")
});
}
And this is the request that I made, very simple:
[HttpGet]
public async Task<ActionResult<IEnumerable<string>>> Get()
{
var message = new Message
{
Token = "dgY8UMXhEZ4:APA91bFnrZTGJKkCCBJHzbghvsvEaq-w-ee1XBAVqAaS-rsmR3Ald23rHGgpfdgVb09r97jDQBVSc6GtDHWtLHWAnn4Lm3EM_j-sh7cu-RaRSrfnk3X124v4co3Q9ID6TxFdGgv7OXWt",
Data = new Dictionary<string, string>
{
{"title", "test" }
}
};
try
{
var fcmResult = await FirebaseMessaging.DefaultInstance.SendAsync(message);
} catch (FirebaseException ex)
{
}
return new string[] { "value1", "value2" };
}
Github test project: https://github.com/kevingoos/FirebaseAdminTest
Solved problem: https://github.com/firebase/firebase-admin-dotnet/issues/73
This happens when the token is invalid/expired or does not belong to the same project as the credentials used to initialize the Admin SDK.

Making http Post request on Gupshup IDE works?

I copied gupshup's document code and modified just url as "http://posttestserver.com/post.php" and it doesn't work.
Anyone has an advice for me?
else if(event.message.toLowerCase() == "post") {
var contextParam = {
"User": {
"userName": "sbCobxxxx",
"Password": "xxxxxxx-9f-4307-9d9a-451f3xxxx075",
"Pin": "16776"
}
};
var url = "http://posttestserver.com/post.php";
var param = JSON.stringify(contextParam);
var header = {"Content-Type": "application/json"};
context.simplehttp.makePost(url, param, header);
}
function HttpResponseHandler(context, event) {
// if(event.geturl === "http://ip-api.com/json")
context.sendResponse(event.getresp);
}
Response returns empty string: ""
Thanks in advance.
Are you testing using Gupshup's emulator? If yes then POST and GET calls with headers and params doesn't work in the emulator as of now. The documentations mentions it. However, you can deploy the code and test it out using Gupshup proxy bot on Facebook messenger and it will work fine.
Here is a screenshot of the testing I did after directly copying your code into the IDE.

Unknown name "view_id" error when querying google analytics reporting API

I am trying to query the Google Analytics Reporting API from a node.js application.
I think I have set up everything correctly on the google-side of things including a service account, but I must be missing a piece.
My application successfully sends usage-data to Google, I can see it come in in the realtime view. I can also query the data using the interactive API explorer.
In my node.js code I authenticate with the API at server startup like so:
var googleapis_key = require('./config/google-api-key.json');
var googleapis = require('googleapis');
var googleapis_jwtClient = new googleapis.auth.JWT(
googleapis_key.client_email,
null,
googleapis_key.private_key,
["https://www.googleapis.com/auth/analytics.readonly"],
null);
var googleapis_analyticsreporting = googleapis.analyticsreporting('v4');
googleapis_jwtClient.authorize(function(err, tokens) {
if (err) {
lStartup.error(err);
lStartup.error("Could not authenticate with google API. Analytics not available.");
} else {
lStartup.info("Successfully authenticated with google service-account.");
lStartup.debug(googleapis_jwtClient.credentials);
}
});
(where lStartup is a log4js logger). I get a positive response back from Google, err is not set and the credentials logged to the console look convincing.
Then later when the relevant client request comes in my server tries to ask google for the data:
var reportingrequests = {
"reportRequests": [
{
"viewID": "138122972",
"dateRanges": [{"startDate": "7daysAgo", "endDate": "yesterday"}],
"metrics": [{"expression": "ga:users"}]
}
]
};
logger.debug(JSON.stringify(reportingrequests));
googleapis_analyticsreporting.reports.batchGet(
{
"resource": reportingrequests,
"auth": googleapis_jwtClient,
},
function(err, response) {
if (err) {
// Failure. Log and report to the client.
console.error("Could not query the Google Analytics reporting API");
console.error(err);
res.writeHead(500, "Internal server error. (Google analytics:" + err + ")");
res.end(JSON.stringify(err));
} else {
// Success, just serve googles result to the client.
res.end(JSON.stringify(response));
}
}
);
The response is an error
[ { message: 'Invalid JSON payload received. Unknown name "view_id" at \'report_requests[0]\': Cannot find field.',
domain: 'global',
reason: 'badRequest' } ] }
What is it trying to tell me here? I do not have properties named view_id or report_requests in my JSON. Although they look suspiciously like mine de-camelcased.
I hate self-answering, but I love solutions!
"viewID": "138122972",
should be
"viewId": "138122972",
Note the lowercase "d".
Ironically the clue to this is in the camelCase to snake_case-conversion. If the parameter name was "viewID" it would propably have been snake_cased to "view_i_d", which is not what is in the error message.
I feel stupid, but also happy to be able to go on.

Resources