I am trying to do HTTP post to a google form, from a C program in my device. For a legacy form, the active form submission URL looks like below. I used these text to do a URL encoded HTTP/1.1 POST, which was successful.
https://spreadsheets.google.com/formResponse?formkey=FORMKEY&ifq&entry.0.single=ENTRY1&entry.2.single=ENTRY2&submit=Submit
For the new google form (whichever you create from google drive now), below is the active submit URL. When I use this for HTTP post, I get the Bad Request with error Code 400.
https://docs.google.com/forms/d/FORMKEY/formResponse?entry.1252261890=ENTRY1&entry.1890412746=ENTRY2
What has changed between old and new google form? I see similar problem faced by somebody elsewhere but no solution so far. Thanks for your help.
This is a javascript (google apps script) POST that is working on a current form (with one field!) Pperhaps you can get what you need from this:
function sendHttpPost() {
var fish = "I am a mackerel";
var payload =
{
"entry.2071121932" : fish
};
// Because payload is a JavaScript object, it will be interpreted as
// an HTML form. (We do not need to specify contentType; it will
// automatically default to either 'application/x-www-form-urlencoded'
// or 'multipart/form-data')
var options =
{
"method" : "POST",
"payload" : payload,
"muteHttpExceptions": true
};
var response = UrlFetchApp.fetch("https://docs.google.com/forms/d/this is the form ... key/formResponse", options);
Logger.log(response.getContentText())
}
Related
I am using Leaflet in my Angular.js map application. One of my resources requires an authorization header with token. I am using the leaflet-realtime plugin (found here: https://github.com/perliedman/leaflet-realtime) to get map updates and therefore need to be able to specify my header when realtime performs a fetch to get the data.
I first tried using another library, fetch-intercept (found here: https://github.com/werk85/fetch-intercept), to intercept the requests and attach the header, but the interceptor was being ignored. I included a console.log in the interceptor and it was never reached.
After more research, I noticed specifying headers is supposed to be supported: https://github.com/perliedman/leaflet-realtime/pull/83. However, I cannot find an example for how to properly attach an authorization token. Here is what I am currently trying:
this.mapRealtime = L.realtime({
url: this.getRealtimeUrl(),
crossOrigin: true,
headers: {"Authorization": "token"},
type: 'json',
},
However, when I check the Network logging from my web browser (Chrome) debugging console, all I see for the Request Headers is:
Provisional headers are shown
Access-Control-Request-Headers: authorization
Access-Control-Request-Method: GET
and the server returns status 403 with errortype MissingAuthenticationTokenException.
Can anyone provide an example of how to correctly attach the token? Thanks!
The realtime Leaflet only take url or json file path and you will be unable to pass headers(auth) as they have patch for it which is not working. I was facing same issue. What I did is following:
realtime = (L as any).realtime(async function (success, error) {
let geodataJson = await self.updateGeoJson();
success(geodataJson);
}, {
interval: 15 * 1000,
onEachFeature: onEachFeature,......
I have pass funtion to realtime and in that function I called simple API with headers
async updateGeoJson() {
await this.api.getMarkersGeoJson().subscribe((res: any) => {
this.geoData = res;
});
return this.geoData; }
On first call it will not get data in from this function so we also need to load data in this.geoData in ngOnInit before initmap.
For me it is working I know this is just work around but this issue is still in leaflet realtime. Hopefully this will work for you
How can I post message as a bot(async) in new hangouts chat without using the Google App Engine. I have gone through the examples, but all of them use App Engine for authentication, but i need to authenticate it without using the same.
Here is a code sample that connects to a chat using an http request and a webhook from Google Hangout Chat with a Python script. Webhooks are the only alternative to using a service account. More info here: https://developers.google.com/hangouts/chat/how-tos/webhooks
`from httplib2 import Http
from json import dumps
#
# Hangouts Chat incoming webhook quickstart
#
def main():
url = '<webhook url here>'
bot_message = {
'text' : 'text go here'}
message_headers = { 'Content-Type': 'application/json; charset=UTF-8'}
http_obj = Http()
response = http_obj.request(
uri=url,
method='POST',
headers=message_headers,
body=dumps(bot_message),
)
print(response)
if __name__ == '__main__':
main()
`
If your bot implementation is with google app script try to do it with google service account and as indicated here an example of async message
// Example bot for Hangouts Chat that demonstrates bot-initiated messages
// by spamming the user every minute.
//
// This bot makes use of the Apps Script OAuth2 library at:
// https://github.com/googlesamples/apps-script-oauth2
//
// Follow the instructions there to add the library to your script.
// When added to a space, we store the space's ID in ScriptProperties.
function onAddToSpace(e) {
PropertiesService.getScriptProperties()
.setProperty(e.space.name, '');
return {
'text': 'Hi! I\'ll post a message here every minute. ' +
'Please remove me after testing or I\'ll keep spamming you!'
};
}
// When removed from a space, we remove the space's ID from ScriptProperties.
function onRemoveFromSpace(e) {
PropertiesService.getScriptProperties()
.deleteProperty(e.space.name);
}
// Add a trigger that invokes this function every minute via the
// "Edit > Current Project's Triggers" menu. When it runs, it will
// post in each space the bot was added to.
function onTrigger() {
var spaceIds = PropertiesService.getScriptProperties()
.getKeys();
var message = { 'text': 'Hi! It\'s now ' + (new Date()) };
for (var i = 0; i < spaceIds.length; ++i) {
postMessage(spaceIds[i], message);
}
}
var SCOPE = 'https://www.googleapis.com/auth/chat.bot';
// The values below are copied from the JSON file downloaded upon
// service account creation.
var SERVICE_ACCOUNT_PRIVATE_KEY = '-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n';
var SERVICE_ACCOUNT_EMAIL = 'service-account#project-id.iam.gserviceaccount.com';
// Posts a message into the given space ID via the API, using
// service account authentication.
function postMessage(spaceId, message) {
var service = OAuth2.createService('chat')
.setTokenUrl('https://accounts.google.com/o/oauth2/token')
.setPrivateKey(SERVICE_ACCOUNT_PRIVATE_KEY)
.setClientId(SERVICE_ACCOUNT_EMAIL)
.setPropertyStore(PropertiesService.getUserProperties())
.setScope(SCOPE);
if (!service.hasAccess()) {
Logger.log('Authentication error: %s', service.getLastError());
return;
}
var url = 'https://chat.googleapis.com/v1/' + spaceId + '/messages';
UrlFetchApp.fetch(url, {
method: 'post',
headers: { 'Authorization': 'Bearer ' + service.getAccessToken() },
contentType: 'application/json',
payload: JSON.stringify(message),
});
}
You need to perform some below steps.
Create a service-account in console.developers.google.com and download the private key in JSON format
Use below modules if you code in python.
from oauth2client.service_account import ServiceAccountCredentials
from googleapiclient.discovery import build, build_from_document
from httplib2 import Http
Below snippet will post the message to user via chat.google.
scopes = ['https://www.googleapis.com/auth/chat.bot']
credentials = ServiceAccountCredentials.from_json_keyfile_name('/path/to/json',
scopes)
http = Http()
credentials.authorize(http)
chat = build('chat', 'v1', http=http)
resp = chat.spaces().messages().create(
parent=space,
body={'text': 'HELLO WORLD'}).execute()
You would require a space name where you can post the code. You will get the same from hangout chat response.
It’s possible to do so using JavaScript, python, (possibly more). You can check out examples here: https://github.com/gsuitedevs/hangouts-chat-samples/tree/master/node/basic-cloud-functions-bot
If you’re using cards and JavaScript I would encourage you to checkout my library here: https://github.com/BaReinhard/hangouts-card-helper
I’m also in the process of creating another example for JavaScript that is more async focused that should provide and example that’s a bit easier to reason about the code. Will link when the PR is pushed.
Edit:
I realize that you mentioned REST api. The above answer is more useful for a specific bot that can be accessed #mentions. However, if you can provide us with a bit more information I can better fix my answer to answer your question.
I'm new to Single Page Application area and I try to develop app using angularjs and Spark framework. I get error 400 bad request when I want to post JSON from my website. Here is code fragment from client side:
app.controller('PostTripCtrl', function($scope, $http) {
$scope.newTrip = {};
$scope.submitForm = function() {
$http({
method : 'POST',
url : 'http://localhost:4567/trips/add',
data : $scope.newTrip,
headers : {
'Content-Type' : 'application/x-www-form-urlencoded'
}
}).success(function(data) {
console.log("ok");
}).error(function(data) {
console.log("error");
console.log($scope.newTrip);
});
};
});
Values that are to be assigned to newTrip are read from appropriate inputs in html file. Here is server-side fragment:
post("/trips/add", (req, res) -> {
String tripOwner = req.queryParams("tripOwner");
String startDate = req.queryParams("startDate");
String startingPlace = req.queryParams("startingPlace");
String tripDestination = req.queryParams("tripDestination");
int tripPrice = Integer.parseInt(req.queryParams("tripPrice"));
int maxNumberOfSeats = Integer.parseInt(req.queryParams("maxNumberOfSeats"));
int seatsAlreadyOccupied = Integer.parseInt(req.queryParams("seatsAlreadyOccupied"));
tripService.createTrip(tripOwner, startDate, startingPlace, tripDestination, tripPrice, maxNumberOfSeats,
seatsAlreadyOccupied);
res.status(201);
return null;
} , json());
At the end I obtain error 400 bad request. It is strange for me that when I want to see output on the console
System.out.println(req.queryParams());
I get json array of objects with values written by me on the website. However, when I want to see such output
System.out.println(req.queryParams("tripOwner"));
I get null. Does anyone have idea what is wrong here?
I think the main problem is that you are sending data to your Spark webservice with the 'Content-Type' : 'application/x-www-form-urlencoded' header. Try sending it as 'Content-Type' : 'application/json' instead, then in your Java code declare a String to receive req.body(), you'll see all your data in there.
Note: When you try to acces your data like this req.queryParams("tripOwner"); you're not accessing post data, but you're seeking for a get parameter called tripOwner, one that could be sent like this http://localhost:8080/trips/add?tripOwner=MyValue.
I would advise using postman to post a request to your server and see if it works. Try a different content type too. Try using curl and play with the various headers you are sending. 400 suggests the wrong data is being sent or expected data is missing or the data is the wrong type but based on your code you've provided I can see nothing wrong (but see below).
When your server receives a request log all request headers being received and see what changing them does. If it works in postman then you can change your client code to mirror the headers postman is using.
Does your spark server validate the data being sent before your controller code is hit? If so ensure you are adhering to all validation rules
Also on looking at your code again your client is sending the data in the post data but your server is expecting the data in the query string and not in the post data?
What happens if your server just sends a 201 response and does nothing else? Does your client get a 201 back? If so it suggests the hook up is working but there is something wrong with the code before you return a 201, build it up slowly to fix this.
Ok, I managed to cope with that using another approach. I used Jackson and ObjectMapper according to Spark documentantion. Thanks for your answers.
You can see more about that here: https://sparktutorials.github.io/2015/04/03/spark-lombok-jackson-reduce-boilerplate.html
You're probably just needed to enable CORS(Cross-origin resource sharing) in your Spark Server, which would have allowed you to access the REST resources outside the original domain of the request.
Spark.options("/*", (request,response)->{
String accessControlRequestHeaders = request.headers("Access-Control-Request-Headers");
if (accessControlRequestHeaders != null) {
response.header("Access-Control-Allow-Headers", accessControlRequestHeaders);
}
String accessControlRequestMethod = request.headers("Access-Control-Request-Method");
if(accessControlRequestMethod != null){
response.header("Access-Control-Allow-Methods", accessControlRequestMethod);
}
return "OK";
});
Spark.before((request,response)->{
response.header("Access-Control-Allow-Origin", "*");
});
Read more about pre-flighted requests here.
I am generating in server side a pre-signed URL request with the following parameters for GeneratePresignedUrlRequest : bucket, key, expiration = in 1 hour and method = PUT.
In my Angular app, I am uploading the file using ng-file-upload
Upload.http({
url: $scope.signedUrl,
method: "PUT",
headers : {
'Content-Type': $scope.file.type
},
data: $scope.file
});
The problem is that I always have a 403 response unless I set the type of the file in GeneratePresignedUrlRequest.contentType.
The problem is that I can't predict in advance what type of file the user will choose (image/png, image/jpeg, text/plain...).
How can I generate a pre-signed url that accept all kinds of content-type ? I tried setting it to null, it keeps sending 403 errors.
Thanks.
I just ran into this problem, and just got it working. Replace your Upload.http code with the following:
var reader = new FileReader();
var xhr = new XMLHttpRequest();
xhr.open("PUT", $scope.signedUrl);
reader.onload = function(evt) {
xhr.send(evt.target.result);
};
reader.readAsArrayBuffer($scope.file);
The problem ends up being that S3 is looking for a specific Content-Type (binary/octet-stream), which it infers when you omit the Content-Type header.
The value from the Content-Type header is a mandatory component of the signature. It isn't possible to pre-sign a PUT URL without knowing the value that will be sent.
A POST upload is more flexible, since you can allow any Content-Type in the signed policy.
One possible solution might be if you keep track of the extension?
eg: ends with ".jpg" -> content type = "image/jpeg", end with ".zip" -> content type = "application/octet-stream".
Ref: get the filename of a fileupload in a document through javascript
I've done a lot of searching and nothing seems to fully address this. I've created a REST API that has a resource to send a message. The path is /api/v1/conversation/{type}/{id}/message. Placing a POST call to that URI will create a message for the given conversation.
Everything works great if I just use $.post('/api/v1/conversation/sample/sample/message', {message: "All your base are belong to us"});
However, I'd like to use Restangular, and for some reason, it is sending the POST data in a way that I have to work with request.body instead of request.POST.get('message'). This is terribly inconvenient if I have to do this with every single server side API.
Here's my Restangular code:
conversation = Restangular.one('conversation', scope.type).one(scope.type_id);
conversation.post('message', {message: "All your base..."})
To clarify, it is POSTing to the correct URI, it just is sending the post data as a payload instead of as form data. How can I configure it to send the post as form data?
Edit:
As a side note, I was able to mitigate this issue by creating a utility function:
def api_fetch_post(request):
post = request.POST
if not post:
try:
post = json.loads(request.body.decode(encoding='UTF-8'))
except:
pass
return post
This way I can accept either type of POST data. Regardless, is there a way to send form data with Restangular?
Yes, there is.
var formData = new FormData();
formData.append('message', $scope.message);
// Or use the form element and have formData = new FormData(formElement).
Restangular.one('conversation', $scope.type).one($scope.type_id)
.withHttpConfig({transformRequest: angular.identity})
.post(formData, null, {'Content-Type': undefined})
.then(function(response){
// Do something with response.
});