I made an Edge extension which task is to redirect the page to another site in specific at certain sites and when the user click a button this second site redirect back to the origin.
This extension works in local network but a small error.
The two site redirect to each other continously.
Somewhere I read it that Edge remove sessionStorage and localStorage in case of redirection in local network so I tried cookie but not much success.
Well I ask for help in this case.
//background.js
const apps = [
['AAA', 'aaa.intra.abc.xx']
];
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
const url = tabs[0].url;
const domain = (new URL(url)).hostname.replace('www.','').toLowerCase();
try {
chrome.cookies.get({ 'url': tabs[0].url, 'name': domain },
function(data){
if (!data) {
const i = apps.findIndex(u => domain.includes(u[1]));
if (i > -1) {
chrome.cookies.set({
url: tabs[0].url,
name: domain,
value: apps[i][0]
});
chrome.tabs.update( tabs[0].id, { url: `http://popup.intra.abc.xx?title=${apps[i][0]}`} );
}
}
}
);
} catch (e) {
alert("Error: " + e);
}
});
});
SOLUTION
manifest.json
{
"manifest_version": 2,
"name": "PopUp",
"version": "1.0",
"background": { "scripts": ["background.js"] },
"permissions": ["webRequest", "webRequestBlocking", "cookies", "<all_urls>"]
}
background.js
const apps = [
['AAA', 'aaa.intra.abc.xx']
];
function logURL(requestDetails) {
const domain = (new URL(requestDetails.url)).hostname.replace('www.','').toLowerCase();
chrome.cookies.get({ 'url': requestDetails.url, 'name': 'status' },
function(data){
if (data === null) {
const i = apps.findIndex(u => domain.includes(u[1]));
if (i > -1) {
chrome.cookies.set({
url: requestDetails.url,
name: "status",
value: "opened"
});
const url = 'http://popup.intra.abc.xx/?title=' + apps[i][0];
chrome.tabs.update( requestDetails.tabId, { url: url} );
}
}
}
);
}
chrome.webRequest.onBeforeRequest.addListener(
logURL,
{urls: ["https://...", "http://.../*", "http://.../*"]},
["blocking"]
);
I had to play with the place of URLs because they should had had better place in the manifest.json permissions array but in case of some URLs it caused ping-pong effect again. So they stayed in onBeforeRequest urls array.
manifest.json
{
"manifest_version": 2,
"name": "PopUp",
"version": "1.0",
"background": { "scripts": ["background.js"] },
"permissions": ["webRequest", "webRequestBlocking", "cookies", "<all_urls>"]
}
background.js
const apps = [
['AAA', 'aaa.intra.abc.xx']
];
function logURL(requestDetails) {
const domain = (new URL(requestDetails.url)).hostname.replace('www.','').toLowerCase();
chrome.cookies.get({ 'url': requestDetails.url, 'name': 'status' },
function(data){
if (data === null) {
const i = apps.findIndex(u => domain.includes(u[1]));
if (i > -1) {
chrome.cookies.set({
url: requestDetails.url,
name: "status",
value: "opened"
});
const url = 'http://popup.intra.abc.xx/?title=' + apps[i][0];
chrome.tabs.update( requestDetails.tabId, { url: url} );
}
}
}
);
}
chrome.webRequest.onBeforeRequest.addListener(
logURL,
{urls: ["https://...", "http://.../*", "http://.../*"]},
["blocking"]
);
I had to play with the place of URLs because they should had had better place in the manifest.json permissions array but in case of some URLs it caused ping-pong effect again. So they stayed in onBeforeRequest urls array.
Related
I use a Dialogflow API as NLP and the interface that we use is Whatsapp API.
my problem is, when I want to bypass Text and Whatsapp client number to Dialogflow (my reference), I didn't found document to explain that. for comparison, the Telegram official integration dialogflow, from the body request we can extract that data like name and Telegram user ID.
const sessionId = phone_number_id; //session ID get from phone number
const sessionPath = sessionClient.projectAgentSessionPath(projectId, sessionId);
const request = {
session: sessionPath,
queryInput: {
text: {
text: msg_body,
languageCode: "id-ID"
},
},
payload: {
data: "testing",
phoneNumber : phone_number_id
}
};
console.log("request", request);
await sessionClient.detectIntent(request).then(responses => {
console.log("DetectIntent", JSON.stringify(responses));
}).catch(err => {
console.error("ERROR:", err);
})
I tried it with request variable like that but in request body in dialogflow fulfillment, it never showed up
{
"responseId": "censored",
"queryResult": {
"queryText": "halo",
"action": "input.welcome",
"parameters": {},
"allRequiredParamsPresent": true,
"fulfillmentText": "error",
"fulfillmentMessages": [
{
"text": {
"text": [
"error"
]
}
}
],
"outputContexts": [
{
"name": "censored",
"parameters": {
"no-input": 0,
"no-match": 0
}
}
],
"intent": {
"name": "censored",
"displayName": "Default Welcome Intent"
},
"intentDetectionConfidence": 1,
"languageCode": "id"
},
"originalDetectIntentRequest": {
"payload": {}
},
"session": "censored"
}
#Maulana ahmad, As you have mentioned in the comment below example code can be referred to extract data from the body request.
const dialogflow = require('dialogflow');
// Import the JSON to gRPC struct converter
const structjson = require('./structjson.js');
// Instantiates a sessison client
const sessionClient = new dialogflow.SessionsClient();
// The path to identify the agent that owns the created intent.
const sessionPath = sessionClient.sessionPath(projectId, sessionId);
// The text query request.
const request = {
session: sessionPath,
queryInput: {
event: {
name: eventName,
parameters: structjson.jsonToStructProto({foo: 'bar'}),
languageCode: languageCode,
},
},
};
sessionClient
.detectIntent(request)
.then(responses => {
console.log('Detected intent');
logQueryResult(sessionClient, responses[0].queryResult);
})
.catch(err => {
console.error('ERROR:', err);
});
This Stack Overflow link can be referred for more information.
Posting the answer as community wiki for the benefit of the community that might encounter this use case in the future.
Feel free to edit this answer for additional information.
I use react-native with graphQL.
Now I can upload one single photo on aws successfully.
But I want to upload multiple files at once.
If I run loop I can successfully upload multiple files on aws as below.
const onValid = ({ caption }) => {
const uploadPhotoArray = selectPhoto.map((sp, index) => {
return new ReactNativeFile({
uri: sp,
name: `${index}.jpg`,
type: "image/jpeg",
});
});
for (let i = 0; i < uploadPhotoArray.length; i++) {
uploadPhotoMutation({
variables: {
caption,
file: uploadPhotoArray[i],
},
});
}
};
But the problem is, if I upload 2 images, then it creates two rows on aws and backend.
In order to make it one row (post) with 2 images, I make file column of backend as Array, not string.
However I think the problem is the frontend.
I wanted to make uploadPhotoArray as array like below.
Array [
ReactNativeFile {
"name": "0.jpg",
"type": "image/jpeg",
"uri": "file:///storage/emulated/0/DCIM/Camera/20220306_020216.jpg",
},
ReactNativeFile {
"name": "1.jpg",
"type": "image/jpeg",
"uri": "file:///storage/emulated/0/DCIM/Camera/20220305_201130.jpg",
},
]
then tried to run uploadPhotoMutation with this array.
uploadPhotoMutation({
variables: {
caption,
file: uploadPhotoArray,
},
});
Then it will pass array data to backend.
But it seems now working.
If I can't pass Array data to backend, which means that one by one is possible, then I need to make this incoming data to array on backend.
But that's also hard for me.
If you want to clarify my question, I can answer in real-item and chat is also possible.
Please give me any idea. :(
backend code
const fileUrl = fileArrayCheck
? await uploadFileToS3(file, loggedInUser.id, "uploads")
: await uploadStringleFileToS3(file, loggedInUser.id, "uploads");
export const uploadStringleFileToS3 = async (file, userId, folderName) => {
console.log(file);
AWS.config.update({
credentials: {
accessKeyId: process.env.AWS_KEY,
secretAccessKey: process.env.AWS_SECRET,
},
});
const { filename, createReadStream } = await file;
const readStream = createReadStream();
const objectName = `${folderName}/${userId}-${Date.now()}-${filename}`;
const { Location } = await new AWS.S3()
.upload({
Bucket: "chungchunonuploads",
Key: objectName,
ACL: "public-read",
Body: readStream,
})
.promise();
return [Location];
};
export const uploadFileToS3 = async (filesToUpload, userId, folderName) => {
const uploadPromises = await filesToUpload.map((file) => {
uploadStringleFileToS3(file, userId, folderName);
});
return Promise.all(uploadPromises);
};
So on the React Native side the console.log is printing this for the image file as in I'm doing console.log(photos[1]) and getting this
{"fileName": "rn_image_picker_lib_temp_0d752f09-0fab-40f0-8c89-13dec3695de0.jpg", "fileSize": 374466, "height": 810, "type": "image/jpeg", "uri": "file:///data/user/0/com.cheersfe/c
ache/rn_image_picker_lib_temp_0d752f09-0fab-40f0-8c89-13dec3695de0.jpg", "width": 1000}
Here is my React Native Code
const createFormData = (photos, body = {}) => {
const data = new FormData();
if (photos.length > 1) {
console.log(photos[1])
data.append("images", photos[1]);
}
Object.keys(body).forEach((key) => {
data.append(key, body[key]);
});
return data;
};
const onAddButtonClick = () => {
if (value === null) {
Alert.alert("Hold On!", "Please select a goal");
} else if (descriptionText === "") {
Alert.alert("Hold On!", "Update description required");
}
setLoading(true);
const body = createFormData(photos, { join_goal: value, body: descriptionText });
postGoalUpdatePost(body).then(response => {
// navigation.navigate("PostsScreen");
setLoading(false);
}).catch(error => {
const errorMessage = `${error.name}: ${error.message}`;
});
setLoading(false);
};
export async function postGoalUpdatePost(body) {
return constructConfig().then(config => {
return axios.post(`${url}/posts/update`, body, config).then(response => {
return response.data;
});
});
}
But on the Django side when I look at request.data['images'] I get this crazy hexstring:
\x7f.x�������uJr|�����a=e��|�\x00��^�=J0�^������\x08\x1a\\\x02;�H�a�a�\x19=�u�K\x01�x䞧�\x0e�{{�\x07\x14���}H�2\x06?.)%�\x7f\x1f�\x0c�RvI������=H-���[��䌏ÿ^��\x00玵�$��<g�\x1d}�\x1d�\x00®7�\x1e���Yr\x7f�\x1f���+&��wт�I�?������$�Ӯz���N?Z�+�\x07�Oo\x7f�?����\x7f\x13���ܒ1����\r����V=J0M�\x7f5�I5�ϹVG���\x189��`�\x7fJ�$��u�1���{\x7f.�չ:7���kuO��\x15���m,����{\x18x�\x7f.]�\x7f�W��s�\x0e=��1�\x00֬�e^��0y$sӧ�\x0ez՛���\x7f3YS\x13��|��+�\x7f\x13��#���;>�k�o�\x7fñ\x1c�\x03�\x0f\x18�;s�\'��ߥ\x19$$�{���O���SI�\x1b�U\x1f�\x0f�O�\x15���}^����֥\x08���u���\x002��|����|���Y�$�\x003�^�A�9�>�j��\x1f����z\x1f��U��\x17�u=z\x10\\��O����b9�V\x18\x04p\x08������Vd�G\x1f��2O�V��\x1f�ک\\u?C��qԛJI[���zT"����_�W+�\x02\x06\x0f$u����\x00����\x15\x19�\x1f��4W\x0b��z$w���'
so clearly it's coming in as a string rather than a file. How do I fix this?
The issue was the format that the upload library was saving the json
{"fileName": "rn_image_picker_lib_temp_0d752f09-0fab-40f0-8c89-13dec3695de0.jpg", "fileSize": 374466, "height": 810, "type": "image/jpeg", "uri": "file:///data/user/0/com.cheersfe/c
ache/rn_image_picker_lib_temp_0d752f09-0fab-40f0-8c89-13dec3695de0.jpg", "width": 1000}
needs to be in
{'name': file_name, 'uri': uri, 'type': type}
format. Then needed 'content-type' to be 'multipart/form-data'
I am trying to trace a serverless express Lambda function using AWSXRay.
I have tried several different approaches to this and nothing seems to work.
If I leave out the aws-xray-sdk-express middleware, I will see all my segments in the Timeline, and see my Lambda function appearing twice in the Trace Map. If I include the express middleware, I will see the middleware segment ('Super Dooper Trace Function') in the Trace Map and just the first subsegment ('MyFirstTrace') in the Timeline (not in the Trace Map).
I am trying to get all Subsegments to appear in both the Timelines and Node Graphs
const AWSXray = require('aws-xray-sdk');
const xrayExpress = require('aws-xray-sdk-express');
const express = require('express');
const awsServerlessExpress = require('aws-serverless-express');
module.exports.handler = async (event, context) => {
const app = express();
app.use(xrayExpress.openSegment('Super Dooper Trace Function'));
app.get('/test', async (req, res) => {
const result = await doWork();
res.send(result);
});
app.use(xrayExpress.closeSegment());
const server = awsServerlessExpress.createServer(app);
return awsServerlessExpress.proxy(server, event, context, 'PROMISE').promise;
}
const doWork = async () => {
const res1 = await traceMyFunction('MyFirstTrace', 3000)
const res2 = await traceMyFunction('MySecondTrace', 3000);
const res3 = await traceMyFunction('MyThirdTrace', 2000);
return [res1, res2, res3];
}
const traceMyFunction = (name, delayMs) => {
return trace(name, async () => {
return delay(delayMs)
});
}
function trace(name, promiseFunction) {
return new Promise((resolve, reject) => {
AWSXray.captureAsyncFunc(name, (subSegment) => {
promiseFunction(subSegment)
.then((result) => {
resolve(result);
subSegment.close();
}).catch((e) => {
subSegment.close();
reject(e)
});
});
});
}
const delay = (ms) => {
return new Promise((res, rej) => {
setTimeout(() => res({ time: ms }), ms)
});
};
This is the resultant XRay Trace
And this is the Trace Raw Data
{
"Duration": 8.278,
"Id": "1-5e2f6cc3-a99e6c08f02ce0aec7ab7121",
"Segments": [
{
"Document": {
"id": "87ca46b60ded68e1",
"name": "Super Dooper Trace Function",
"start_time": 1580166338.92,
"end_time": 1580166347.198,
"http": {
"request": {
"url": "http://localhost/test",
"method": "GET",
"user_agent": "",
"client_ip": ""
},
"response": {
"status": 200
}
},
"aws": {
"xray": {
"sdk": "X-Ray for Node.js",
"sdk_version": "2.5.0",
"package": "aws-xray-sdk"
}
},
"service": {
"version": "unknown",
"runtime": "node",
"runtime_version": "v12.13.0",
"name": "unknown"
},
"trace_id": "1-5e2f6cc3-a99e6c08f02ce0aec7ab7121",
"subsegments": [
{
"id": "98e9f32273700e6e",
"name": "MyFirstTrace",
"start_time": 1580166339.078,
"end_time": 1580166342.082
}
]
},
"Id": "87ca46b60ded68e1"
}
]
}
Serverless Express has known incompatabilities with the current X-Ray SDK - due to the fact Lambda generates its own Segment, then the Express middleware tries to create one as well. We're planning to address this in the near future.
https://github.com/aws/aws-xray-sdk-node/issues/45
For the full explanation, see this thread: https://github.com/aws/aws-xray-sdk-node/issues/30
My api basically returns something like this:
GET /api/projects/
{
"count": 26,
"next": "http://127.0.0.1:8000/api/projects/?page=2",
"previous": null,
"results": [
{
"id": 21,
"name": "Project A",
...
},
{
"id": 19,
"name": "Project B",
...
},
...
]
}
Using NgResource, I am able to query the api and get the data like this:
var PROJECT = $resource('/api/projects/:id/', {id:'#id'},{
query : {
method : 'GET',
isArray : false
}
});
factory.project_list = function(callback) {
PROJECT.query({},function(project_list){
factory.project_list = project_list.results;
callback();
});
};
My different projects are now available in factory.project_list. The issue here is that each item in factory.project_list are not ngResource items. So I can't call methods such as .$save(), .$update()...
I saw a transformResponse() function but I'm not able to get it working easily...
Do you have any idea what could be the best approach here ?
This is what worked for me:
app.config(['$resourceProvider', function($resourceProvider) {
$resourceProvider.defaults.stripTrailingSlashes = false;
}]);
services.factory('Project', ['$resource',
function($resource) {
return $resource('api/project/:id/', {}, {
query: {
method: 'GET',
url: 'api/projects/',
isArray: true,
transformResponse: function(data, headers) {
return angular.fromJson(data).results;
},
},
});
}
]);