SendGrid: "The provided authorization grant is invalid, expired, or revoked" - java

I am setting up an app to send emails to clients. I am using Java and SendGrid to create this app, but I am having issues with the SendGrid authorization
I am getting the error:
java.io.IOException: Request returned status Code 401Body:{"errors":[{"message":"The provided authorization grant is invalid, expired, or revoked","field":null,"help":null}]}
Reading through some other posts with similar issues it seems most get resolved because people were using the API Key ID instead of the API Key. I have already checked to make sure that I am using the full key so I don't think that is the issue.
I have also tried to create a new API Key but that just gives the same issue. Finally, I have tried doing a similar call using Postman and that works just fine with the same API Keys.
This is the main class I am using to send emails.
import com.sendgrid.*;
import com.sendgrid.helpers.mail.Mail;
import com.sendgrid.helpers.mail.objects.Content;
import com.sendgrid.helpers.mail.objects.Email;
import java.io.IOException;
public class SendEmail {
public static void main(String[] args) throws IOException{
Email from = new Email("FROM_EMAIL");
String subject = "Sending with Twilio(?) is fun";
Email to = new Email("TO_EMAIL");
Content content = new Content("text/plain", "and easy to to anywhere, even with Java");
Mail mail = new Mail(from, subject, to, content);
SendGrid sg = new SendGrid(System.getenv("API_KEY"));
Request request = new Request();
try {
request.setMethod(Method.POST);
request.setEndpoint("mail/send");
request.setBody(mail.build());
Response response = sg.api(request);
System.out.println(response.getStatusCode());
System.out.println(response.getBody());
System.out.println(response.getHeaders());
} catch (IOException ex) {
throw(ex);
}
}
I then call this class in my main class through this snippet:
try{
SendEmail.main(email);
} catch(IOException ex){
System.out.println(ex);
}
The "email" string is just a placeholder as otherwise I get an error saying that I need to have an array when I call the class. (Not sure why that is, could that be the root of the problem?)
Obviously sensitive information has been removed so that's why some of the fields look off.
By the way, I followed the tutorial in this github:
https://github.com/sendgrid/sendgrid-java
Let me know what you think.
Thanks in advance!

I think your environment variable was not setup properly. Try to execute the program without "System.getenv" as below.
SendGrid sg = new SendGrid("YOUR_API_KEY");

My apologies. I did not know "System.getenv" would get the environmental variables. I set up environmental variables and the issue is resolved.

Related

How to list storage classes using Kubernetes client

I am using below line of code to get details about a particular PVC
response = await `serverModule.kubeclient.api.v1.namespaces(ns).persistentvolumeclaims(pvc).get();`
The corresponding API for above call is readNamespacedPersistentVolumeClaim with below format
GET /api/v1/namespaces/{namespace}/persistentvolumeclaims/{name}
Now, I am trying to call readStorageClass using same convention as above
response = await serverModule.kubeclient.apis.storage.k8s.io.v1.storageclasses(sc).get();
As you can see in the link, GET /apis/storage.k8s.io/v1/storageclasses/{name} is the format, I have used above syntax. But for some reason the code fails with error
Exported kubeclient, ready to process requests
TypeError: Cannot read property 'k8s' of undefined
What is the syntax error that I have made. I tried various combinations but none worked.
This issue is listing PersistentVolumeClaim is a part of coreV1Api of kubernetes and listing StorageClass is the part of StorageV1beta1Api. Following it the simplest code for listing storage class using JAVA client:
ApiClient defaultClient = Configuration.getDefaultApiClient();
// Configure API key authorization: BearerToken
ApiKeyAuth BearerToken = (ApiKeyAuth) defaultClient.getAuthentication("BearerToken");
BearerToken.setApiKey("YOUR API KEY");
// Uncomment the following line to set a prefix for the API key, e.g. "Token" (defaults to null)
//BearerToken.setApiKeyPrefix("Token");
StorageV1beta1Api apiInstance = new StorageV1beta1Api();
try {
V1beta1StorageClassList result = apiInstance.listStorageClass();
System.out.println(result);
} catch (ApiException e) {
System.err.println("Exception when calling StorageV1beta1Api#listStorageClass");
e.printStackTrace();
}
Following is the official documentation link for your reference:
https://github.com/kubernetes-client/java/blob/master/kubernetes/docs/StorageV1beta1Api.md#listStorageClass
Hope this helps.
Use client.apis["storage.k8s.io"].v1.storageclasses.get() , Applicable to any api containing dots.
Hope it helps

Send an error to appengine endpoint client

In my GAE endpoint, in my user register API method, I check whether a user already exists with the given username. If a user already exists, I need to send an error to the endpoint client.
Currently I throw an exception like below from endpoint.
User user = ofy().load().key(Key.create(User.class, username)).now();
if (user != null) {
throw new BadRequestException("Username already exists");
}
Then in endpoint client, I catch the exception like below.
try {
gaeEndpoint.registerUser(mEmail, mPassword).execute();
} catch (HttpResponseException e) {
mErrorMessage = e.getContent();
} catch (IOException e) {
mErrorMessage = "Failed to communicate with server. Please check your internet connection.";
}
When endpoint throws a BadRequestException, client gets HttpResponseException e and e.getContent() contains a json string including the error message string sent from endpoint. I need to parse json to get the actual error message sent from server.
Even though this works, I feel that there should be a better way to send an error message to the client from the endpoint. So, does anyone know a better (or a recommended) way of doing this?
I think you're doing everything right.
HTTP is designed to send a response with 4xx code and meaningful content to a user. It can be HTML for a browser, JSON for an api client or anything that can provide some context to the client.
If you're worried about using exceptions, that's fine too. Of course, you can prepare a response with a manually set status code, but that doesn't change anything, it's just more code. It's also less likely that you'll create a bug when you're using exceptions in this case.

Using Https Protocol for downloading data from Flickr

Since June 2014, all API keys just work via HTTPS only.Flickr deprecate non-SSL access to the API. There is another Post, but It's for 6 years ago which is before this event.
I know how to download data from Flickr, and I know it should work, but the problem is the library doesn't support Https.
I am trying to count the number of Images that have been shared by a user. I used getPeopleInterface().getPublicPhotos(userId,100,1) method.
but the problem is, it returns back Error 403 for URL!
I checked the Url in browser, and the Error is "SSL is required."
So I changed http to https in the URL and it worked. I do not know how I can change it in my code.
public class GetUsersPhotos {
public static void main(String[] args) throws Exception{
String key = "";
String secret = "";
String userId = "78069284#N00";
Transport t = new REST();
Flickr f = new Flickr(key, secret, t);
PhotoList list = f.getPeopleInterface().getPublicPhotos(userId,100,1);
System.out.println(list);
}
}
I solved my problem. The Flickrapi 1.2,doesn't support Https Protocol. What I did I downloaded Flickr4Java.jar which I checked and support Https, and then add the latest log4j jar file. then, it works.

setting content type in rest assured

I'm trying to invoke a rest call using rest assured. My API accepts, "application/json" as content type and I need to set in the call. I set the content type as mentioned below.
Option 1
Response resp1 = given().log().all().header("Content-Type","application/json")
.body(inputPayLoad).when().post(addUserUrl);
System.out.println("Status code - " +resp1.getStatusCode());
Option 2
Response resp1 = given().log().all().contentType("application/json")
.body(inputPayLoad).when().post(addUserUrl);
The response I get is "415" (indicates that "Unsupported media type ").
I tried invoking the same api using plain java code and it works. For some mysterious reason, I cudn't get it working through RA.
HttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost(addUserUrl);
StringEntity input = new StringEntity(inputPayLoad);
input.setContentType("application/json");
post.setEntity(input);
HttpResponse response = client.execute(post);
System.out.println(response.getEntity().getContent());
/*
BufferedReader rd = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
String line = "";
while ((line = rd.readLine()) != null) {
System.out.println("Output -- " +line);
}
I faced similar issue while working with rest-assured 2.7 version. I tried setting both the contentType and also accept to application/json but it didn't work. Adding carriage feed and new line characters at the end as the following worked for me.
RestAssured.given().contentType("application/json\r\n")
The API seems to be missing to add new line characters after Content-Type header due to which the server is not able to differentiate between the media type and the rest of the request content and hence throwing the error 415 - "Unsupported media type".
Here is the complete POST example using CONTENT_TYPE as JSON.
import io.restassured.http.ContentType;
RequestSpecification request=new RequestSpecBuilder().build();
ResponseSpecification response=new ResponseSpecBuilder().build();
#Test
public void test(){
User user=new User();
given()
.spec(request)
.contentType(ContentType.JSON)
.body(user)
.post(API_ENDPOINT)
.then()
.statusCode(200).log().all();
}
Give a try
given().contentType(ContentType.JSON).body(inputPayLoad.toString)
This might possibly be the case with your test. Try this.
https://github.com/rest-assured/rest-assured/wiki/Usage#avoid-adding-the-charset-to-content-type-header-automatically
Avoid adding the charset to content-type header automatically
By default REST Assured adds the charset header automatically. To
disable this completely you can configure the EncoderConfig like this:
RestAssured.config = RestAssured.config(config().encoderConfig(encoderConfig().appendDefaultContentCharsetToContentTypeIfUndefined(false));
As mentioned in previous posts there is a method:
RequestSpecification.contentType(String value)
I did not work for me too. But after upgrade to the newest version (in this moment 2.9.0) it works. So please upgrade :)
I was facing something similar and after some time we noticed the problem was actually coming from the server side. Please check your call on Postman and see if when it's triggered you need to change it from HTML to JSON. If you need to do that, the backend may need to force the response to be in JSON format by adding its content type. Even if it's encoded in JSON you're still may need to do that.
Thats the line of code we added:
header('Content-type:application/json;charset=utf-8');
.
public function renderError($err){
header('Content-type:application/json;charset=utf-8');
echo json_encode(array(
'success' => false,
'err' => $err
));
}
And that's what was happening on the backend:
Hope that can help somehow. :)
import io.restassured.RestAssured;
import io.restassured.http.ContentType;
import static org.hamcrest.Matchers.is;
import org.testng.annotations.Test;
import static io.restassured.RestAssured.given;
public class googleMapsGetLocation {
#Test
public void getLocation() {
RestAssured.baseURI = "https://maps.googleapis.com";
given().param("location", "-33.8670522,151.1957362")
.param("radius", "500")
.param("key", "AIzaSyAONLkrlUKcoW-oYeQjUo44y5rpME9DV0k").when()
.get("/maps/api/place/nearbysearch/json").then().assertThat()
.statusCode(200).and().contentType(ContentType.JSON)
.body("results[0].name", is("Sydney"));
}
}
For your First option can you please try adding this header too and sending the request?
.header("Accept","application/json")

Different results back accessing the same php json request from android and pc web browser

I am having a problem where when I put the querying URL into a web browser on my Mac the API send the data back as I am expecting but when I use the exact same URL within my app on android I get the following error: {"SC":"400","VSM":"Incorrect parameter passed on URL","VERNUM":"1.2"}. It is just a simple test to see if the database in my app is up to date. Is this an API problem or something i'm doing wrong in the app? I have no control over the API functionality so if it's a problem with that then I will have to get somebody else to sort it out. the code I am using is below.
String URL = "http://Url.com/?p=api&request=check_for_changes";
Log.v("Value", URL);
JSONObject jsonObjSend = new JSONObject();
try
{
jsonObjSend.put("dataset_version_number", 1.1);
// Output the JSON object we're sending to Logcat:
Log.v("Response", jsonObjSend.toString(2));
}
catch (JSONException e)
{
Log.i("Response", "Error happened here");
}
try
{
jsonObjRecv = HttpClient.SendHttpPost(URL, jsonObjSend);
Log.v("SC", jsonObjRecv.get("SC").toString());
}
catch (JSONException e){
}
The HttpClient object is from a class I have used many times before to just read the response from the server so i'm not going to post the code on here as it's not relevent and quite long.
The Answer come in the form of me being an idiot and trying to use a POST Request on a URL which doesnt accept JSON and only needs a GET Request. So I only need to query the URL and get the response rather than try and send the data via a POSTusing JSON.

Categories