PUT/GET with Payload using Restangular - angularjs

I am using Restangular in one of my works
The server guys have give me the following calls which i need to integrate on the AngularJS client
PUT api/partners/password – RequestPayload[{password,confirmpassword}]
partner id is being sent in the header
GET api/partners/password/forgot/ - Request Payload [{emailaddress}]
partner id is being sent in the header
The javascript code that I have written to call these services is as follow
Restangular.all('Partners').one('Password').put(params); - sends params as query string
Restangular.all('Partners').one('Password').one('Forgot').get(params); - sends object in the url
I have tried other ways but it simply doesn't make the correct call.
Help me out guys!

So, for point #1. it puts the object at hand, not another object. So you have 2 options:
Option 1
var passReq = Restangular.all('Partners').one('Password');
passReq.confirmPassword = ....
passReq.put(); // confirmPassword and the params of the object will be sent
Option 2 is
var passReq = Restangular.all('Partners').one('Password').customPUT(obj);
For Point #2, you cannot send a request body (payload) in the GET unfortunately.

Related

How do I set up Azure API Management to accept POST with form data fields and pass them through to a legacy API

I have a legacy API that is expecting to be called by POST of a form with 3 form fields (each containing a string). I would like to wrap this call in the Azure API Management.
I'm hoping I've missed something basic, but I assumed that the API service would pass through what it received to my legacy API.
I created:
- an api
- an operation (POST)
- a backend service
- credentials to login to backend service
I can call the service through either the test link or through postman. It definitely is hitting the backend API - but it doesn't seem to be passing my multi-part form fields with it.
Do I need to create a representation?
Any links to guidance?
I have done a similar thing for setting up a token API which communicates with AAD API and it accepts the form data. I accept the ClientId and ClienSecret in my APIM exposed API as input. e.g.
{
"ClientID":"",
"ClientSecret": ""
}
This is passed to the backend as shown below
<set-backend-service base-url="https://login.microsoftonline.com/someguid/oauth2/v2.0" />
<set-header name="Content-Type" exists-action="override">
<value>application/x-www-form-urlencoded</value>
</set-header>
<set-body>#{
JObject request = JObject.Parse(context.Request.Body.As<string>(preserveContent:true));
string clientId = (string)request?["ClientId"];
string clientSecret = (string)request?["ClientSecret"];
string scope = "api://someguid/.default";
string grantType = "client_credentials";
string response = $"client_id={clientId}&client_secret={clientSecret}&scope={scope}&grant_type={grantType}";
return response;
}</set-body>

http.post Sends the 3rd variable empty

The code gets the username and password from the user's inputs. Then it gets the device Mac Address using the 2 functions. I know this part can be simplified, I'm open to recommendations.
I'm 100% sure that $scope.data.macAddr is not empty because I'm able to print it on the console. I was worried about the data type, but I confirmed it that is a string using the "type" of, which returns 'String'.
Update: Also when I inspect the post headers only username and password are sending over.
I don't understand why http.post sends an empty/ not passing it at all to the server.
P.S I know about the MD5 risks. I'm using MD5 just to test my code. Eventually, at the end, I will use HTTPS/SSL with Bcrypt
var link = 'http://app.example.com/api.php';
MacAddress.getMacAddress(function(macAddress){$scope.getMacAddr(macAddress);}, function(fail){console.log(fail);});
$scope.getMacAddr = function(macAddr) {
$scope.macAddr = macAddr;
$scope.data.macAddr = macAddr;
}
$http.post(link, {
username: md5.createHash($scope.data.username),
password: md5.createHash($scope.data.password),
macAddr: $scope.data.macAddr
}).then(function(res) {
console.log(typeof ($scope.data.macAddr));
OK, so you have two asynchronous calls here. One is the call to get the MAC address, and one is the http post. Here is what happens:
At T0: You call getMacAddress(), passing a callback function that will be called, later, when the mac address is available
At T1: You send an HTTP request, passing a callback to then()
At T1000: The mac address is available: the callback passed at step 1 is called, and initializes $scope.data.macAddr
At T150000: the http response is available. The callpack passed at step 2 is called, and prints $scope.data.macAddr.
Send your http request from inside the callback function that you pass at step 1, when the mac address is available.

Why is Gmail returning a UID outside the range specified by UID FETCH command?

When I run a fetch command UID FETCH 170930:170930 BODY[] I get the response 88924 FETCH (UID 170920 FLAGS (\Seen)). I wasn't expecting to retrieve a message with a UID out of the range specified. Is this normal IMAP behaviour? The 170930 UID came from watching the folder with an IdleManager only moments earlier, so I have no reason to believe that a message with that UID doesn't exist on the server.
The fetch request I've posted here is a guess based on the Java code I'm using to execute it. At the very least it should still be requesting only messages within that range:
Argument args = new Argument();
args.writeString(Long.toString(start) + ":" + Long.toString(end));
args.writeString("BODY[]");
Response[] r = protocol.command("UID FETCH", args);
Response response = r[r.length - 1];
An IMAP server is required to send you FETCH responses in certain cases. Sometimes the server is required to wait with responses, but it's never required not to send you any.
If you send a command that requires two response, and someone else does something that requires one response to you, then you get three responses. That something might be to change the flag on a message (requires FETCH ... FLAGS ... to you, although there's no promptness requirement) or send you some mail (requires EXISTS to you).

Getting a users mailbox current history Id

I'd like to start syncing a users mailbox going forward so I need the most recent historyId of the users mailbox. There doesn't seem to be a way to get this with one API call.
The gmail.users.history.list endpoint contains a historyId which seems to be what I need, from the docs:
historyId unsigned long The ID of the mailbox's current history record.
However to get a valid response from this endpoint you must provide a startHistoryId as a parameter.
The only alternative I see is to make a request to list the users messages, get the most recent history id from that, then make a request to gmail.users.history.list providing that historyid to get the most recent one.
Other ideas?
Did you check out https://developers.google.com/gmail/api/guides/sync ?
Depending on what your use-case is, to avoid races between your current state and when you start to forward sync, you'll need to provide an appropriate historyId. If there were a "get current history ID" then anything between your previous state and when you got those results would be lost. If you don't have any particular existing state (e.g. only want to get updates and don't care about anything before that) then you can use any historyId returned (e.g. on a message or thread) as you mention.
Small example for C# users (mentioned in comments by #EricDeFriez).
Nuget package Google.Apis.Gmail.v1 must be installed. See also quickstart for .NET developers.
var service = new GmailService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = ApplicationName,
});
var req = service.Users.GetProfile("me");
req.Fields = "historyId";
var res = req.Execute();
Console.WriteLine("HistoryId: " + res.HistoryId);
This answer is related to the Java Gmail API Client Library using a service account.
I found that the gmail.users.getprofile() will not work as the object that it returns is of type Class Gmail.Users.GetProfile which does not have an interface to getting a historyId.
com.google.api.services.gmail.model.Profile actually has a getHistoryId() function, but calling service.users().getProfile() will return a Class Gmail.Users.GetProfileobject instead.
To get around this, I use the history.list() function which will always return the latest historyId as part of its response.
Gmail service = createGmailService(userId); //Authenticate
BigInteger startHistoryId = BigInteger.valueOf(historyId);
ListHistoryResponse response = service.users().history().list("me")
.setStartHistoryId(startHistoryId).setMaxResults(Long.valueOf(1)).execute();
I set the max number of results to be 1 to limit the unnecessary data that I get returned back and I will receive a payload that looks like:
{"history":[{"id":"XXX","messages":[{"id":"XXX","threadId":"XXX"}]}],"historyId":"123456","nextPageToken":"XXX"}
The historyId (123456) will be the current historyId of the user. You can grab that historyId using response.getHistoryId()
You can also see that the latest historyId is given in the response if you use the API tester for Users.history: list
https://developers.google.com/gmail/api/v1/reference/users/history/list

Google Channel API sending message with token

In documents it says 'client_id' part can actually be the token, however it doesn't work. Anyone know why?
https://developers.google.com/appengine/docs/python/channel/functions
If the client_id parameter is actually a token returned by a create_channel call then send_message can be used for different versions of the app. For instance you could create the channel on the front end and then send messages from a backend of the app.
the reason i want to use this, is because i want to send messages to anonymous users as well, without requiring them to login. i don't know if it is possible to assign them a 'client_id' if token doesn't work.
this is how i am creating the token
user = users.get_current_user()
if user:
token = channel.create_channel(user.user_id())
else:
token = channel.create_channel(str(uuid.uuid4()))
then injecting into client
template_values = {
'token' : token,
}
on the client side open the channel
openChannel = function() {
var token = '{{ token }}';
var channel = new goog.appengine.Channel(token);
var handler = {
'onopen': onOpened,
'onmessage': onMessage,
'onerror': function() {},
'onclose': function() {}
};
var socket = channel.open(handler);
socket.onopen = onOpened;
socket.onmessage = onMessage;
}
now send a message
var xhr = new XMLHttpRequest();
xhr.open('POST', path, true);
xhr.send();
in the server,
when the message is received send back a message using the token
channel.send_message(token, someMessage)
back to client
onMessage = function(m) {
alert("you have some message");
}
this sequence works fine if client_id() is used instead of token when calling send_message
In response to btevfik's initial question: Allowing tokens or client_id in send_message is a feature released in 1.7.5 (very recently). Some people may not be familiar with it yet so therefore they suggest to use client_id. Both should work!
The only thing that I can see in your code is the fact that you should not rely on token variable to be correct in between two requests. They may not even land on the same instance of the app. If you share your code with more details I may be able to spot something. The proper way would be to either store the token in the datastore or pass it from the client as a parameter when you send the message that will trigger a message back.
The purpose of this feature was to allow people to send messages from backends (or other versions). Before was not possible whereas now you can do it if you use directly the tokens instead of the client_id.
Long time this post has been around, but just curious about your usage of the token global variable?
I don't see this code:
global token
before you set the token
user = users.get_current_user()
if user:
token = channel.create_channel(user.user_id())
else:
token = channel.create_channel(str(uuid.uuid4()))
If that code is missing, then token will be set in the local scope of the function above and not globally. So, the token value used later will be None (or to what ever the token was initialised with.)
Just a thought, if its still relevant.
I don't think you actually have a problem here.
You are able to send messages to users that are logged in or not.
The problem you are having I think is knowing that there are multiple ways to use the channel API re: tokens.
https://developers.google.com/appengine/docs/python/channel/overview#Life_of_a_Typical_Channel_Message
In this example, it shows the JavaScript client explicitly requests a token and sends its Client ID to the server. In contrast, you could choose to design your application to inject the token into the client before the page loads in the browser, or some other implementation if preferred.
This diagram shows the creation of a channel on the server. In this
example, it shows the JavaScript client explicitly requests a token
and sends its Client ID to the server. In contrast, you could choose
to design your application to inject the token into the client before
the page loads in the browser, or some other implementation if
preferred.
Here's my demo implementation, hope it helps somehow: https://github.com/Paul1234321/channelapidemo.git
Here's the code for creating the channel on GAE:
client_id = str(uuid.uuid4()).replace("-",'')
channel_token = channel.create_channel(client_id)
And in the JS:
channel = new goog.appengine.Channel('{{ token }}');
Have a look at it in action: http://pppredictor.appspot.com/
You shouldn't store request-specific values in global variables. Store them in a cookie or pass them as a request parameter instead.

Resources