On a remote server, there is an HTML page with javascript. The user visits this page, makes some settings, and runs an API query.
How can I ensure that all API queries are routed independently from the user's location through a specific IP address, which is my proxy gateway? How is it possible with javascript?
This is the whole function that runs API query:
function Query(keyword)
{
var qk = keyword;
var queryresult = '';
queryflag = true;
$.ajax({
url: window.location.protocol + "//apiv3.example.com/lookup",
jsonp: "jsonp",
dataType: "jsonp",
data: {
q: qk,
client: "chrome",
hl: document.querySelector("select").value
},
success: function(res) {
var rL = res[1];
var i = 0;
for(i = 0; i < rL.length; i++)
{
var currents = CleanVal(rL[i]);
if(hashMapResults[currents] != 1)
{
hashMapResults[currents] = 1;
SaveLatest(CleanVal(rL[i]));
ktq[ktq.length] = currents;
var j = 0;
for(j = 0; j < 26; j++)
{
var chr = String.fromCharCode(97 + j);
var currentx = currents + ' ' + chr;
ktq[ktq.length] = currentx;
hashMapResults[currentx] = 1;
}
}
}
FilterAndDisplay();
var textarea = document.getElementById("input");
textarea.scrollTop = textarea.scrollHeight;
queryflag = false;
}
});
}
You can't control routing between the user and the endpoint.
If you want data to go through your server then the URL you pass to $.ajax needs to be that of your server.
Related
In Google Apps Script, I'm using some code I adapted from a project I found. It calls an API endpoint and lays out the data in a spreadsheet. I was able to get it to loop through multiple API calls in order to pull data from multiple documents. However, the code breaks if it finds a document with no data. In this case, I want it to just skip that iteration and start again at the next cardIds.forEach iteration.
Here's a link to a sample sheet.
I tried:
if (response == "") {
return;
}
But no dice. Here's the full code (also it's very inefficient. I have params on their twice because I'm not sure how to consolidate them with all the functions inside other functions..)
const DATA_SHEET = "Data";
const USERNAME_CELL = "B1";
const API_TOKEN_CELL = "B2";
const CARD_ID_COL = "Cards!B:B"
const DATA_RANGE = "A4:C"
var getNextPage = function(response) {
var url = response.getAllHeaders().Link;
if (!url) {
return "";
}
return /<([^>]+)/.exec(url)[1];
};
var getIt = function(path, username, apiToken) {
var params = {
"method": "GET",
"muteHttpExceptions": true,
"headers": {
"Content-Type": "application/json",
"Authorization": "Basic " + Utilities.base64Encode(username + ":" + apiToken),
"x-guru-application": "spreadsheet",
"X-Amzn-Trace-Id": "GApp=spreadsheet"
}
};
var response = UrlFetchApp.fetch(path, params);
var data = JSON.parse(response.getContentText());
// check if there's another page of results.
var nextPage = getNextPage(response);
if (nextPage) {
data.nextPage = nextPage;
};
return data;
};
var getItAll = function(url, username, apiToken, callback) {
var data = [];
while (url) {
var page = getIt(url, username, apiToken);
var startIndex = data.length;
page.forEach(function(a) {
data.push(a);
});
// get the url of the next page of results.
url = page.nextPage;
if (callback) {
// the second parameter is whether we're done or not.
// if there's a url for the next page that means we're not done yet.
callback(data, startIndex, page.length, url ? false : true);
}
}
return data;
};
function eachCard() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(DATA_SHEET);
sheet.getRange(DATA_RANGE).clearContent();
var username = sheet.getRange(USERNAME_CELL).getValue();
var apiToken = sheet.getRange(API_TOKEN_CELL).getValue();
var cardIds = sheet.getRange(CARD_ID_COL).getValues().flat().filter(r=>r!="");
var params = {
"method": "GET",
"muteHttpExceptions": true,
"headers": {
"Content-Type": "application/json",
"Authorization": "Basic " + Utilities.base64Encode(username + ":" + apiToken),
"x-guru-application": "spreadsheet",
"X-Amzn-Trace-Id": "GApp=spreadsheet"
}
};
cardIds.forEach(function (cardId) {
var fullUrl = "https://api.getguru.com/api/v1/cards/"+cardId+"/comments"
var cardComments = getItAll(fullUrl, username, apiToken);
var fullUrl = "https://api.getguru.com/api/v1/cards/"+cardId+"/extended"
var response = UrlFetchApp.fetch(fullUrl, params);
var cardData = JSON.parse(response.getContentText());
var sheetLastRow = sheet.getLastRow();
var range = sheet.getRange("A" + sheetLastRow);
if (range.getValue() !== "") {
var lastRow = sheetLastRow+1;
} else {
var lastRow = range.getNextDataCell(SpreadsheetApp.Direction.UP).getRow()+1;
}
cardComments.forEach(function(comment, commentIndex) {
sheet.getRange(lastRow + commentIndex, 1).setValue(comment.dateCreated);
sheet.getRange(lastRow + commentIndex, 1 + 1).setValue(comment.content);
sheet.getRange(lastRow + commentIndex, 1 + 2).setValue(cardData.preferredPhrase);
});
});
}
Currently, I'm using the code (written in Apps Script) given below to sync data from multiple google sheets to the database with the help of URLs. When the "sheetLinks" is given URL of sheets within a single google sheet file, it doesn't read the gid of the URL which is the only thing that differs between multiple sheets within a google sheet file thus making the for loop to run twice(as it is considering only the base URL which is same in both).
const sheetLinks = [
"https://docs.google.com/spreadsheets/d/same/edit#gid=0",
"https://docs.google.com/spreadsheets/d/same/edit#gid=654836738"
];
let baseUrl = "https://something/api";
function syncData() {
for (filenum = 0; filenum < sheetLinks.length; filenum++) {
let spreadsheet = SpreadsheetApp.openByUrl(sheetLinks[filenum]);
let values = spreadsheet.getDataRange().getValues();
for (let y = 1; y < values.length; y++)
{
let data = {};
data.name = values[y][11].toString();
data.platform = values[y][5].toString();
data.platform_link = values[y][6].toString();
let dbId = values[y][0];
let responseData = {};
if (dbId) {
responseData = updateSession(dbId, data);
console.log("Session updated! session ID: " + responseData.id);
} else {
responseData = createSession(data);
// write the id to the dbId cell
let actualRowNumber = y + 1; // y + 1 because we start the loop from y 1
spreadsheet.getRange("A" + actualRowNumber).setValue(responseData.id);
console.log("Session created! New session ID: " + responseData.id);
}
y++;
}
}
function apiRequest(url, method, data) {
let options = {
method,
contentType: "application/json",
payload: JSON.stringify(data),
muteHttpExceptions: true,
};
return UrlFetchApp.fetch(url, options);
}
function createSession(sessionData) {
let url = baseUrl + "/session";
let response = apiRequest(url, "post", sessionData);
console.log(response.getContentText());
let responseData = JSON.parse(response.getContentText());
return responseData;
}
function updateSession(sessionId, sessionData) {
let url = baseUrl + "/session/" + sessionId;
let response = apiRequest(url, "patch", sessionData);
let responseData = JSON.parse(response.getContentText());
return responseData;
}
}
So I am trying to send message to LINE Notify from Google Spreadsheets via google form responses, I already testing the API with Postman and it works, I got the Notification, however it doesn't works on the Apps Script Code. here's the error log:
function autoFillPendataanKontak(e) {
var nama = e.values[1];
var nim = e.values[2];
var bidang = e.values[3];
var file = DriveApp.getFileById('------');
var doc = DocumentApp.openById(file.getId());
var body = doc.getBody();
function sendLineNotify(messageNama, messageBidang) {
var token = ["------"];
var options = {
"method": "post",
"payload": messageNama + " telah mendaftar di Bidang " + messageBidang,
"headers": {
"Authorization": "Bearer " + token
}
};
UrlFetchApp.fetch("https://notify-api.line.me/api/notify", options);
}
function appendTable(variabel1, variabel2){
var rangePSDI = null;
var searchElement = body.findElement(DocumentApp.ElementType.TABLE, rangePSDI);
element = searchElement.getElement();
table = element.asTable();
if (bidang == 'PSDI') {
body.replaceText('{{a}}', variabel1);
body.replaceText('{{b}}', variabel2);
var tr = table.appendTableRow();
var ukur = table.getNumRows();
ukur -= 3;
tr.appendTableCell(ukur+1);
tr.appendTableCell("{{a}}");
tr.appendTableCell("{{b}}");
} else if (bidang == 'PSDM') {
body.replaceText('{{c}}', variabel1);
body.replaceText('{{d}}', variabel2);
var tr = table.appendTableRow();
var ukur = table.getNumRows();
ukur -= 3;
tr.appendTableCell(ukur + 1);
tr.appendTableCell("{{c}}");
tr.appendTableCell("{{d}}");
}
}
appendTable(nama, nim);
sendLineNotify(nama, bidang);
doc.saveAndClose();
}
Solved the problem, I just forgot the "message=" on payload
"payload": "message=" + messageNama + " telah mendaftar di Bidang " + messageBidang,
I am trying to send data from a javascript function that generates a random string upon the page loading to a Django view. I don't know how to structure the script tag to send the data after the page has loaded and the views.py to receive the data. I am new to javascript and don't quite know how to go about this. I appreciate any help provided.
index.html
<script>
function makeid(length) {
var result = '';
var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
var charactersLength = characters.length;
for ( var i = 0; i < length; i++ ) {
result += characters.charAt(Math.floor(Math.random() * charactersLength));
}
return result;
}
console.log(makeid(9));
</script>
You can use ajax to send data to Django view like following code.
javascript:
function makeid(length) {
var result = '';
var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
var charactersLength = characters.length;
for ( var i = 0; i < length; i++ ) {
result += characters.charAt(Math.floor(Math.random() * charactersLength));
}
$.ajax({
type: "GET",
url: '/my_def_in_view',
data: {
"result": result,
},
dataType: "json",
success: function (data) {
// any process in data
alert("successfull")
},
failure: function () {
alert("failure");
}
});
}
urls.py:
urlpatterns = [
url(r'^my_def_in_view$', views.my_def_in_view, name='my_def_in_view'),
...
]
views.py:
def my_def_in_view(request):
result = request.GET.get('result', None)
# Any process that you want
data = {
# Data that you want to send to javascript function
}
return JsonResponse(data)
If it was successfull it goes back to "success" part.
you can do that in two ways:
Tradicional with ajax
Websockets: With django channels
If you want to send a bit of information, an ajax request is enough, you have to set and address and a view to receive the POST or GET ajax request.
I recommend to you use pure JS, not jquery
For example, this is a call to refresh a captcha image....
/*Agregar boton refresh al lado del campo input*/
let captcha_field =
document.getElementById('captcha-field-registro_1').parentNode;
let refresh_button=document.createElement('BUTTON');
refresh_button.addEventListener('click',refresh_captcha)
refresh_button.innerHTML = "Refrescar Captcha"; // Insert text
captcha_field.appendChild(refresh_button);
let url_captcha= location.protocol + "//" +
window.location.hostname + ":" +
location.port + "/captcha/refresh/";
let id_captcha_0="captcha-field-registro_0"
function refresh_captcha(){
let xhr = new XMLHttpRequest();
xhr.open('GET', url_captcha, true);
xhr.onload = function recv_captcha_load(event){
console.log("event received", event,
"state",xhr.readyState);
let data_txt = xhr.responseText;
let data_json = JSON.parse(data_txt);
console.log("Data json", data_json);
if (xhr.readyState==4){
if (xhr.status==200){
console.log("LOAD Se ha recibido esta informaciĆ³n", event);
let captcha_img=document.getElementsByClassName('captcha')[0];
console.log("Catpcha img dom", captcha_img);
captcha_img.setAttribute('src', data_json['image_url'])
document.getElementById(id_captcha_0).value=data_json['key']
}
else{
console.log("Error al recibir")
}
}
};
var csrftoken = getCookie('csrftoken');
xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
xhr.setRequestHeader("X-CSRFToken", csrftoken);
xhr.send();
}
function getCookie(name) {
let cookieValue = null;
if (document.cookie && document.cookie !== '') {
var cookies = document.cookie.split(';');
for (let i = 0; i < cookies.length; i++) {
let cookie = cookies[i].trim();
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) === (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
I am developing a html application for Android and I am trying to load images in a list view. Data specific to list items is being served by multiple xml files. I am using ajax to load xml files and populate the list items. Problem I am facing here is that there are 164 list items. Hence, 164 images and 10 xml files to load. my loader function exhausts after two iterations. It does read the xml files but it's unable to dynamically create list items and populate them with images after two iterations. I believe it's due to stack limitations. I can't think of alternate solution. If somebody could suggest an alternate solution that will be highly appreciated. Below is my loader function. It's a recursive function:
function loadChannels() {
$.ajax({
type: "GET",
url: curURL,
dataType: "xml",
error: function(){ console.log('Error Loading Channel XML'); },
success: function(nXml) {
var noOfItems = parseInt($($(nXml).find('total_items')[0]).text(), 10);
var startIdx = parseInt($($(nXml).find('item_startidx')[0]).text(), 10);
var allItems = $(nXml).find('item');
$(allItems).each(function() {
var obj = $("<li><span id='cont-thumb'></span><span id='cont-name'></span></li>");
$("#content-scroller ul").append($(obj));
var imgURL = $($(this).find('item_image')[0]).text();
var contThumb = $(obj).children()[0];
$(contThumb).css("background-image", 'url('+imgURL+')');
var name = $($(this).find('name')[0]).text();
var contName = $(obj).children()[1];
$(contName).text(name).css('text-align', 'center');
var url = $($(this).find('link')[0]).text();
$(obj).data('item_link', url);
$(obj).bind('click', onJPContSelected);
});
if(startIdx+allItems.length < noOfItems){
var newIdx = new Number(startIdx+allItems.length);
var tokens = curURL.split("/");
tokens[tokens.length-2] = newIdx.toString(10);
curURL = "http:/";
for(var i=2; i<tokens.length; i++)
curURL = curURL + "/" + tokens[i];
loadChannels();
}
}
});
}
try to remove the recursion with an outer loop - something like that:
function loadChannels(){
var stopFlag = false;
// request the pages one after another till done
while(!stopFlag)
{
$.ajax({
type: "GET",
url: curURL,
dataType: "xml",
error: function(){
console.log('Error Loading Channel XML');
errorFlaf = true;
},
success: function(nXml) {
var noOfItems = parseInt($($(nXml).find('total_items')[0]).text(), 10);
var startIdx = parseInt($($(nXml).find('item_startidx')[0]).text(), 10);
var allItems = $(nXml).find('item');
$(allItems).each(function() {
var obj = $("<li><span id='cont-thumb'></span><span id='cont-name'></span></li>");
$("#content-scroller ul").append($(obj));
var imgURL = $($(this).find('item_image')[0]).text();
var contThumb = $(obj).children()[0];
$(contThumb).css("background-image", 'url('+imgURL+')');
var name = $($(this).find('name')[0]).text();
var contName = $(obj).children()[1];
$(contName).text(name).css('text-align', 'center');
var url = $($(this).find('link')[0]).text();
$(obj).data('item_link', url);
$(obj).bind('click', onJPContSelected);
});
if(startIdx+allItems.length < noOfItems){
var newIdx = new Number(startIdx+allItems.length);
var tokens = curURL.split("/");
tokens[tokens.length-2] = newIdx.toString(10);
curURL = "http:/";
for(var i=2; i<tokens.length; i++)
curURL = curURL + "/" + tokens[i];
// lets disable the recursion
// loadChannels();
}
else {
stopFlag = true;
}
}
});
}
}