Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pagination Use Case #25

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 81 additions & 0 deletions sample-proxies/pagination/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# API Pagination

This sample shows how to perform a simple "Pagination of data" using javascript policy.

It caches the offset and limit based on user_id header and based on that it paginates.

It uses these policies:

CacheLimit.xml - It caches the Limit value
CacheOffset.xml - It caches the offset value
CacheResponse.xml - Response Cache
ContentListings.xml - Policy that mocks up 100 book entries
GetPaginationParams.xml - This policy extracts query parameters.
LookupLimit.xml - Looks up the cache to get the cached Limit
LookupOffset.xml - This looks up the offset value
Pagination.xml - This is the javascript policy to paginate the data.


#Explaination
You have to set two headers:

user_id : this is used to store the pagination configuration(offset and limit) into cache by user_id.
bypass-cache: TRUE value means ignore cache, FALSE value means lookup for a response in cache. This value is affecting just the response cache policy.

Ex:

request.header.user_id = tester1
request.header.bypass-cache = true

Once you set the pagination configuration by user_id, the queryparams are not needed anymore, however you must provide a user_id to retrieve the pagination configuration and the next page. Once you reach the last page, the next request will retrieve the first page.


Complete example:

First request (first page and pagination configuration):
curl -H "user_id: tester1" -H "bypass-cache: true" http://${host}/v1/demo/content-listing?offset=0&limit=10

This will return the first 10 entries.

Second and further requests (next page or first page after you reach the last page):

curl -H "user_id: tester1" -H "bypass-cache: false" http://${host}/v1/demo/content-listing

This will return the next 10 entries.

You can start over the pagination process by providing new pagination configuration (offset and limit queryparams).


# Set up

* The username and password that you use to login to enterprise.apigee.com.
* The name of the organization in which you have an account. Login to
enterprise.apigee.com and check account settings.

# Configure

Update `/setup/setenv.sh` with your environment details

# Import and deploy sample project

To deploy, run `$ sh deploy.sh`

To test, run `$ sh invoke.sh`

# Get help

For assistance, post to the [Apigee Developer Forum](http://support.apigee.com)

Copyright © 2013 Apigee Corporation

Licensed under the Apache License, Version 2.0 (the "License"); you may not use
this file except in compliance with the License. You may obtain a copy
of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Binary file added sample-proxies/pagination/apiproxy/.DS_Store
Binary file not shown.
29 changes: 29 additions & 0 deletions sample-proxies/pagination/apiproxy/Pagination.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<APIProxy revision="1" name="Pagination">
<ConfigurationVersion minorVersion="0" majorVersion="4"/>
<CreatedAt>1379217095696</CreatedAt>
<CreatedBy>[email protected]</CreatedBy>
<Description>Content Listing</Description>
<DisplayName>DirectTVDemo</DisplayName>
<LastModifiedAt>1379217095696</LastModifiedAt>
<LastModifiedBy>[email protected]</LastModifiedBy>
<Policies>
<Policy>CacheLimit</Policy>
<Policy>CacheOffset</Policy>
<Policy>CacheResponse</Policy>
<Policy>ContentListings</Policy>
<Policy>GetPaginationParams</Policy>
<Policy>LookupLimit</Policy>
<Policy>LookupOffset</Policy>
<Policy>Pagination</Policy>
</Policies>
<ProxyEndpoints>
<ProxyEndpoint>default</ProxyEndpoint>
</ProxyEndpoints>
<Resources>
<Resource>jsc://paginate.js</Resource>
<Resource>java://DirectTVContentListings.jar</Resource>
</Resources>
<TargetServers/>
<TargetEndpoints/>
</APIProxy>
18 changes: 18 additions & 0 deletions sample-proxies/pagination/apiproxy/policies/CacheLimit.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<PopulateCache enabled="true" continueOnError="false" async="false" name="CacheLimit">
<DisplayName>CacheLimit</DisplayName>
<FaultRules/>
<Properties/>
<CacheKey>
<Prefix>ContentListings</Prefix>
<KeyFragment>Pagination</KeyFragment>
<KeyFragment>Limit</KeyFragment>
<KeyFragment ref="request.header.user_id"></KeyFragment>
</CacheKey>
<CacheResource>PaginationCache</CacheResource>
<Scope>Exclusive</Scope>
<ExpirySettings>
<TimeoutInSec>1800</TimeoutInSec>
</ExpirySettings>
<Source>limit</Source>
</PopulateCache>
18 changes: 18 additions & 0 deletions sample-proxies/pagination/apiproxy/policies/CacheOffset.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<PopulateCache enabled="true" continueOnError="false" async="false" name="CacheOffset">
<DisplayName>CacheOffset</DisplayName>
<FaultRules/>
<Properties/>
<CacheKey>
<Prefix>ContentListings</Prefix>
<KeyFragment>Pagination</KeyFragment>
<KeyFragment>Offset</KeyFragment>
<KeyFragment ref="request.header.user_id"></KeyFragment>
</CacheKey>
<CacheResource>PaginationCache</CacheResource>
<Scope>Exclusive</Scope>
<ExpirySettings>
<TimeoutInSec>1800</TimeoutInSec>
</ExpirySettings>
<Source>offset</Source>
</PopulateCache>
19 changes: 19 additions & 0 deletions sample-proxies/pagination/apiproxy/policies/CacheResponse.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ResponseCache enabled="true" continueOnError="false" async="false" name="CacheResponse">
<DisplayName>CacheResponse</DisplayName>
<FaultRules/>
<Properties/>
<CacheKey>
<Prefix>ContentListings</Prefix>
<KeyFragment>Response</KeyFragment>
</CacheKey>
<CacheResource>PaginationCache</CacheResource>
<Scope>Exclusive</Scope>
<ExpirySettings>
<ExpiryDate></ExpiryDate>
<TimeOfDay></TimeOfDay>
<TimeoutInSec ref="">1800</TimeoutInSec>
</ExpirySettings>
<SkipCacheLookup>request.header.bypass-cache = &quot;true&quot;</SkipCacheLookup>
<SkipCachePopulation></SkipCachePopulation>
</ResponseCache>
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Javascript timeLimit="1000" enabled="true" continueOnError="false" async="false" name="ContentListings">
<DisplayName>ContentListings</DisplayName>
<FaultRules/>
<Properties/>
<ResourceURL>jsc://contentlisting.js</ResourceURL>
</Javascript>
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ExtractVariables enabled="true" continueOnError="false" async="false" name="GetPaginationParams">
<DisplayName>GetPaginationParams</DisplayName>
<FaultRules/>
<Properties/>
<QueryParam name="limit">
<Pattern ignoreCase="true">{limit}</Pattern>
</QueryParam>
<QueryParam name="offset">
<Pattern ignoreCase="true">{offset}</Pattern>
</QueryParam>
<QueryParam name="dir">
<Pattern ignoreCase="true">{dir}</Pattern>
</QueryParam>
<IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
</ExtractVariables>
15 changes: 15 additions & 0 deletions sample-proxies/pagination/apiproxy/policies/LookupLimit.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<LookupCache enabled="true" continueOnError="false" async="false" name="LookupLimit">
<DisplayName>LookupLimit</DisplayName>
<FaultRules/>
<Properties/>
<CacheKey>
<Prefix>ContentListings</Prefix>
<KeyFragment>Pagination</KeyFragment>
<KeyFragment>Limit</KeyFragment>
<KeyFragment ref="request.header.user_id"></KeyFragment>
</CacheKey>
<CacheResource>PaginationCache</CacheResource>
<Scope>Exclusive</Scope>
<AssignTo>limit</AssignTo>
</LookupCache>
15 changes: 15 additions & 0 deletions sample-proxies/pagination/apiproxy/policies/LookupOffset.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<LookupCache enabled="true" continueOnError="false" async="false" name="LookupOffset">
<DisplayName>LookupOffset</DisplayName>
<FaultRules/>
<Properties/>
<CacheKey>
<Prefix>ContentListings</Prefix>
<KeyFragment>Pagination</KeyFragment>
<KeyFragment>Offset</KeyFragment>
<KeyFragment ref="request.header.user_id"></KeyFragment>
</CacheKey>
<CacheResource>PaginationCache</CacheResource>
<Scope>Exclusive</Scope>
<AssignTo>offset</AssignTo>
</LookupCache>
7 changes: 7 additions & 0 deletions sample-proxies/pagination/apiproxy/policies/Pagination.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Javascript timeLimit="1000" enabled="true" continueOnError="false" async="false" name="Pagination">
<DisplayName>Pagination</DisplayName>
<FaultRules/>
<Properties/>
<ResourceURL>jsc://paginate.js</ResourceURL>
</Javascript>
68 changes: 68 additions & 0 deletions sample-proxies/pagination/apiproxy/proxies/default.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ProxyEndpoint name="default">
<Description></Description>
<FaultRules/>
<Flows>
<Flow name="content-listing">
<Description></Description>
<Request>
<Step>
<FaultRules/>
<Name>GetPaginationParams</Name>
</Step>
<Step>
<FaultRules/>
<Name>CacheResponse</Name>
</Step>
<Step>
<Condition>request.queryparam.offset = null or request.queryparam.offset = \&quot;\&quot;</Condition>
<FaultRules/>
<Name>LookupOffset</Name>
</Step>
<Step>
<Condition>request.queryparam.limit = null or request.queryparam.limit = \&quot;\&quot;</Condition>
<FaultRules/>
<Name>LookupLimit</Name>
</Step>
</Request>
<Response>
<Step>
<FaultRules/>
<Name>ContentListings</Name>
</Step>
<Step>
<FaultRules/>
<Name>CacheResponse</Name>
</Step>
<Step>
<FaultRules/>
<Name>Pagination</Name>
</Step>
<Step>
<FaultRules/>
<Name>CacheOffset</Name>
</Step>
<Step>
<FaultRules/>
<Name>CacheLimit</Name>
</Step>
</Response>
<Condition>(proxy.pathsuffix MatchesPath &quot;/content-listing&quot;) and (request.verb = &quot;GET&quot;)</Condition>
</Flow>
</Flows>
<PostFlow name="PostFlow">
<Request/>
<Response/>
</PostFlow>
<PreFlow name="PreFlow">
<Request/>
<Response/>
</PreFlow>
<HTTPProxyConnection>
<BasePath>/v1/paginate</BasePath>
<Properties/>
<VirtualHost>default</VirtualHost>
<VirtualHost>secure</VirtualHost>
</HTTPProxyConnection>
<RouteRule name="noroute"/>
</ProxyEndpoint>
18 changes: 18 additions & 0 deletions sample-proxies/pagination/apiproxy/resources/jsc/contentlisting.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
var books = {
book: []
};


for (var i=0 ; i < 100 ; i++) {

books.book.push({
"id" : i,
"title" : "book title " + i,
"author" : "book author " + i,
"comments" : "book comments " + i
});

}

context.setVariable("response.content", JSON.stringify(books));

24 changes: 24 additions & 0 deletions sample-proxies/pagination/apiproxy/resources/jsc/paginate.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
var contentListingsJSON = JSON.parse(context.proxyResponse.content);
var listingsLength = contentListingsJSON.book.length;
var offset = +context.getVariable("offset");
var limit = +context.getVariable("limit");
var temp = offset;
var offset_plus_limit = offset+limit;
context.setVariable("offset_plus_limit", offset_plus_limit);
var contentBriefPage = new Array();
while(temp < listingsLength) {
if(temp >= offset && temp < offset_plus_limit) {
contentBriefPage.push(contentListingsJSON.book[temp]);
} else if(temp >= offset+limit){
break;
}
temp++;
}
if(temp < offset_plus_limit || temp == listingsLength) {
context.setVariable("offset", 0);
} else {
context.setVariable("offset", temp);
}
contentListingsJSON.book = contentBriefPage;
context.proxyResponse.content = JSON.stringify(contentListingsJSON);
context.proxyResponse.headers["Content-Type"] = "application/json";
20 changes: 20 additions & 0 deletions sample-proxies/pagination/deploy.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#!/bin/bash

source ../../setup/setenv.sh

echo "Enter your password for the Apigee Enterprise organization $org, followed by [ENTER]:"

read -s password

echo Creating cache

curl -X POST -H "Content-type:text/xml" -d @paginate-cache.xml https://api.enterprise.apigee.com/v1/o/$org/environments/$env/caches -u $username:$password


echo Deploying $proxy to $env on $url using $username and $org

../../tools/deploy.py -n pagination -u $username:$password -o $org -h $url -e $env -p / -d ../pagination

echo "If 'State: deployed', then your API Proxy is ready to be invoked."

echo "Run 'invoke.sh'"
18 changes: 18 additions & 0 deletions sample-proxies/pagination/invoke.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
v#!/bin/bash

echo Using org and environment configured in /setup/setenv.sh

source ../../setup/setenv.sh

echo "Enter your password for the Apigee Enterprise organization, followed by [ENTER]:"

read -s password

set -x

curl -H "user_id : tester1" -H "bypass-cache : true" "http://$org-$env.apigee.net/v1/paginate/content-listing?offset=0&limit=20"

echo Now use without query parameter

curl -H "user_id : tester1" -H "bypass-cache : false" "http://$org-$env.apigee.net/v1/paginate/content-listing"

Loading