Tuesday, August 2, 2016

[WSO2 APIM] How to Retrieve Information about an API call, using a Custom Sequence

Most of the time when you call an API, you need to send user information to the backend service. The usual way to do that is with JWT tokens. There are API Manager docs on how to do that.

But if you want to send just few data values for one or two APIs only, you can write a simple custom sequence and attach it to the APIs.

Here is a sample sequence. Here we're creating 2 transport headers for username and API name, which are to be sent to backend.

 
    <sequence xmlns="http://ws.apache.org/ns/synapse" name="admin--Temp:v1.0.0--In">  
          <property name="UserName" scope="transport" expression="$ctx:api.ut.userName"/>  
          <property name="ApiName" scope="transport" expression="$ctx:API_NAME"/>  
          <log level="custom">  
              <property name="User" expression="$trp:UserName"/>  
              <property name="API" expression="$trp:ApiName"/>  
          </log>  
     </sequence>
  

Here is a list of information you can retrieve in above manner. Sample data for each key is given inside brackets.
  • API_NAME (eg: MyAPI)
  • AM_KEY_TYPE (eg: PRODUCTION)
  • REST_SUB_REQUEST_PATH (eg: /resource/pathparam)
  • SYNAPSE_REST_API (eg: admin--Temp:v1.0.0)
  • SYNAPSE_REST_API_VERSION (eg: 1.0.0)
  • TRANSPORT_IN_NAME (eg: https)
  • REST_API_CONTEXT (eg: /context/1.0.0)
  • API_ELECTED_RESOURCE (eg: /resource/{playerId})
  • REST_FULL_REQUEST_PATH (eg: /context/1.0.0/resource/pathparam)
  • api.ut.HTTP_METHOD (eg: GET)
  • api.ut.application.name (eg: DefaultApplication)
  • api.ut.apiPublisher (eg: admin@carbon.super)
  • api.ut.userId (eg: bhathiya@carbon.super)
  • api.ut.consumerKey (eg: 1IVxJBSKeo793IUYk4EtwvZv8eUa)
  • api.ut.userName (eg: bhathiya@carbon.super)
  • api.ut.application.id (eg: 1)
  • api.ut.hostName (eg: 10.100.0.119)
  • uri.var.playerId (eg: pathparam)

EXTRA:

Following throttling related information can be retrieved in _throttle_out_handler_.xml

  • THROTTLED_OUT_REASON (eg. APPLICATION_LIMIT_EXCEEDED)
  • ERROR_CODE (eg. 900803)
  • ERROR_MESSAGE (eg. Message throttled out)
  • NEXT_ACCESS_TIME (eg. 1523883780000)
  • BLOCKED_REASON (eg. Request blocked as it violates defined blocking conditions)


26 comments:

  1. Hi Bharathiya,
    am able to get APIName but not userName , Please reply how to get userName .

    ReplyDelete
    Replies
    1. Is it empty?
      What is the grant type you used to generate the token to access this API?

      Delete
  2. thanks it is working , but I want to get scimId , is it possible? please help

    ReplyDelete
    Replies
    1. You need to call these SCIM APIs for that.

      https://docs.wso2.com/display/IS530/SCIM+APIs

      for example, you can search users like this.

      curl -k --user admin:admin 'https://localhost:9443/wso2/scim/Users?filter=username+eq+alice'

      Delete


  3. Hi

    Below is not working like this am trying to scim id fromn jwt token

    ReplyDelete
  4. What about logging throttling metadata / ploicies ? Thanks

    ReplyDelete
    Replies
    1. You can access throttling related information when a request is throttled out. But custom sequnces are not invoked in that case. Therefore, you can access those information in '_throttle_out_handler_.xml'. Updated the post with details.

      Delete
  5. Hi Bhathiya,

    Can you please let us know how get request body to validate for 'json injection' in Mediation policy (wso2 2.1.0 APIM ).
    or Is it possible to read request body in mediation policy .

    Thanks,
    Bharath K

    ReplyDelete
  6. Hello,

    We are using multitenents on the apimanager and EI. I have to differentiate the environment depending on the domain name. Is there a way where I can retrieve only the domain name ?

    ReplyDelete
    Replies
    1. The question is not clear. You want to get the tenant domain? If yes, you can get it from the username or publisher name.

      Delete
  7. how can i get the client ip who is accessing my API ?

    ReplyDelete
    Replies
    1. If you have a loadbalancer, use this.

      get-property('transport','X-Forwarded-For')

      If not, use this.

      get-property('axis2','REMOTE_ADDR')

      Ref:
      [1] http://shammijayasinghe.blogspot.com/2016/04/how-to-get-clients-ip-address-in-wso2.html
      [2] http://firzhanblogger.blogspot.com/2014/12/how-to-get-api-request-originator-ip.html

      Delete
    2. Thanks for the response... i tried as suggested by you but it is always giving me 127.0.0.1 even though i am accessing my application using my IP and browser also showing remote address which is my IP

      Delete
    3. Plz create a question in stackoverflow with wso2am tag. explain the issue with details.

      Delete
  8. API response caching not working on version 3.0

    ReplyDelete
  9. Hello,

    Is there a way that I can pass the "ApiName" to EI? Or access from EI, without a shared registry.

    ReplyDelete
    Replies
    1. I assume the EI is the backend of your API. Then you. can send it as an http header like this.

      Delete
    2. << property name="ApiName" scope="transport" expression="$ctx:API_NAME"/>

      Delete
    3. Hi Bathiya,

      I'm sorry for the late response, but I am unable to catch it from the EI as a header. What am I missing? Is it possible to catch it in a usual way of $trp ? could you let me know what would be the EI level configurations?

      Thanks in advance :)

      Delete
    4. In the sequence i'm sending it as a header to the EI


      But from EI i am unable to assign it to a property using $trp:ApiNameTwo.

      Delete
    5. Sequence
      << header expression="$ctx:API_NAME" name="ApiNameTwo" scope="transport"/>

      Delete
    6. It's should be like this. (at EI)

      Sequence
      << header expression="$trp:API_NAME" name="ApiNameTwo" scope="transport"/>

      Delete
    7. If this doesn't work, please create a stackoverflow question with complete details and wso2-am tag.

      Delete
  10. Hi Bhathiya,

    Thanks for this wonderful blog..

    I am stucked with one issue..hope it can be resolved with your help.

    My scenario is I want to use multi tenant feature and want to inject rather append the tenant id or tenant domain to my backend url to fetch only tenant specific data from backend application..
    I want to use single generic api for all the tenants and request will append the tenant info to api to get the logged in tenant specifc response.

    Can you suggest how I can achieve the same

    ReplyDelete
  11. My understanding suggest that if api gateway can append those tenant info(id) to the url may be by using message mediation that it may work but not getting the exact way of doing

    ReplyDelete