Skip to content
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
69 changes: 67 additions & 2 deletions Readme.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,72 @@
# Httpex

Apex library for HTTP callouts.
Apex library for HTTP callouts.
## Usage
You can use it with variety of request methods, authentication types or contexts.

### Request methods
Library is able to execute GET, POST, PUT, PATCH, DELET, HEAD.
POST example:
```
Object result = new HttpClientAura(
new HttpClientProviderAuthProvider('SampleAuthProviderName'))
.post('https://foo.com'
+ '/v1/resource/baz/post'
, '{"fizz":"buzz"}');
```

### Authentication types
Library supports several authentication schemes - AuthProvider, Named credentials, Cookie based authentication or basic username/password authentication, for example:
```
static Object postQuxByParams(String params){
return
new HttpClientAura(
new HttpClientProviderBasic('admin', 'hunter2'))
.post('https://foo.com'
+ '/v2/qux/post',
params);
}
```

### Contexts

#### Usage in Lightning server side controllers
Library provides basic catching of errors and reporting them via AuraHandledException that is readable on client side. Example call:
```
@AuraEnabled public static Object getFoo() {
return
new HttpClientAura(
new HttpClientProviderNamedCredentials('SampleNamedCredential'))
.get('https://foo.com'
+ '/v3/resource/foo/get');
}
```

#### Usage elsewhere
```
new HttpClient(
new HttpClientProviderAuthProvider('SampleAuthProviderName'))
.get('https://foo.com'
+ '/v1/resource/foo/get');
```

#### Calling internal API's
```
final static String endpoint = '/services/data/';
final static String apiVersion = 'v43.0';
final static String query = '/tooling/query?q=';
final static String param = 'SELECT Description, EndpointUrl, FullName, IsActive, ManageableState, NamespacePrefix, ProtocolMismatch, SiteName, Metadata FROM RemoteProxy';
final static String sobjectApi = '/tooling/sobjects/RemoteProxy/';
@AuraEnabled public static Object Query(){
HttpClientProviderSelf self = new HttpClientProviderSelf();
return new HttpClientAura(self)
.get(self.getBaseUrl() + endpoint + apiVersion + query + EncodingUtil.urlEncode(param, 'UTF-8'));
}
```

See more at https://github.com/metacursion/RemoteSitesService


<a href="https://githubsfdeploy.herokuapp.com" target="_blank">
<img alt="Deploy to Salesforce" src="https://raw.githubusercontent.com/afawcett/githubsfdeploy/master/deploy.png">
</a>
</a>
Empty file modified src/classes/HttpCalloutException.cls
100644 → 100755
Empty file.
Empty file modified src/classes/HttpCalloutException.cls-meta.xml
100644 → 100755
Empty file.
32 changes: 18 additions & 14 deletions src/classes/HttpClient.cls
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,40 +1,41 @@
public with sharing class HttpClient {

public ICredentialsProvider credentials { get; set; }
public with sharing virtual class HttpClient {
final static Integer CALLOUT_TIMEOUT = 20000;
public HttpClientProviderInterface credentials { get; set; }

public HttpClient(){}

public HttpClient(ICredentialsProvider credentials) {
public HttpClient(HttpClientProviderInterface credentials) {
this.credentials = credentials;
}

public HttpResponse get(String endpoint) {
public virtual Object get(String endpoint) {
return callout(endpoint, '', 'GET');
}

public HttpResponse post(String endpoint, String payload) {
public virtual Object post(String endpoint, String payload) {
return callout(endpoint, payload, 'POST');
}

public HttpResponse put(String endpoint, String payload) {
public virtual Object put(String endpoint, String payload) {
return callout(endpoint, payload, 'PUT');
}

public HttpResponse patch(String endpoint, String payload) {
public virtual Object patch(String endpoint, String payload) {
return callout(endpoint, payload, 'PATCH');
}

public HttpResponse del(String endpoint) {
public virtual Object del(String endpoint) {
return callout(endpoint, '', 'DELETE');
}

public HttpResponse head(String endpoint) {
public virtual Object head(String endpoint) {
return callout(endpoint, '', 'HEAD');
}

public HttpResponse callout(String endpoint, String payload, String method) {
Http http = new Http();
HttpRequest request = new HttpRequest();
request.setTimeout(CALLOUT_TIMEOUT);
request.setEndpoint(endpoint);
request.setMethod(method);
if(new String[]{'POST', 'PATCH', 'PUT'}.contains( method )){
Expand All @@ -43,15 +44,18 @@ public with sharing class HttpClient {
}

if(credentials != null) {
if(credentials instanceof NamedCredentialsProvider) {
if(credentials instanceof HttpClientProviderNamedCredentials) {
endpoint = endpoint.startsWith('/') ? endpoint : '/' + endpoint;
request.setEndpoint(credentials.getHeader() + endpoint);
}
else {
} else if(credentials instanceof HttpClientProviderCookie) {
request.setHeader('Cookie', credentials.getHeader());
} else if(credentials instanceof HttpClientProviderBearer) {
request.setHeader('Authorization', credentials.getHeader());
} else {
request.setHeader('Authorization', credentials.getHeader());
}
}

return http.send(request);
}
}
}
Empty file modified src/classes/HttpClient.cls-meta.xml
100644 → 100755
Empty file.
76 changes: 76 additions & 0 deletions src/classes/HttpClientAura.cls
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
public class HttpClientAura extends HttpClient {
public HttpClientAura(HttpClientProviderInterface credentials) {
super.credentials = credentials;
}
public override Object get(String endpoint) {
try {
return parse((HttpResponse)super.get(endpoint));
} catch( Exception e ){
AuraHandledException ex = new AuraHandledException( e.getMessage() );
ex.setMessage( e.getMessage() );
throw ex;
}
}
public override Object post(String endpoint, String payload) {
try {
return parse((HttpResponse)super.post(endpoint, payload));
} catch( Exception e ){
AuraHandledException ex = new AuraHandledException( e.getMessage() );
ex.setMessage( e.getMessage() );
throw ex;
}
}
public override Object put(String endpoint, String payload) {
try {
return parse((HttpResponse)super.put(endpoint, payload));
} catch( Exception e ){
AuraHandledException ex = new AuraHandledException( e.getMessage() );
ex.setMessage( e.getMessage() );
throw ex;
}
}
public override Object patch(String endpoint, String payload) {
try {
return parse((HttpResponse)super.patch(endpoint, payload));
} catch( Exception e ){
AuraHandledException ex = new AuraHandledException( e.getMessage() );
ex.setMessage( e.getMessage() );
throw ex;
}
}
public override Object del(String endpoint) {
try {
return parse((HttpResponse)super.del(endpoint));
} catch( Exception e ){
AuraHandledException ex = new AuraHandledException( e.getMessage() );
ex.setMessage( e.getMessage() );
throw ex;
}
}
public override Object head(String endpoint) {
try {
return parse((HttpResponse)super.head(endpoint));
} catch( Exception e ){
AuraHandledException ex = new AuraHandledException( e.getMessage() );
ex.setMessage( e.getMessage() );
throw ex;
}
}
public Object parse(HttpResponse response){
if ( response.getStatusCode() < 300 ) {
try {
return JSON.deserializeUntyped( response.getBody() );
} catch( Exception e ){
AuraHandledException ex = new AuraHandledException( e.getMessage() );
ex.setMessage( e.getMessage() );
throw ex;
}
} else {
System.debug(LoggingLevel.ERROR, response.getBody());
String error = response.getStatusCode() + ': ' + response.getStatus();
AuraHandledException ex = new AuraHandledException(error);
ex.setMessage( error );
throw ex;
}
}
}
Empty file modified src/classes/HttpClientBasicMock.cls
100644 → 100755
Empty file.
Empty file modified src/classes/HttpClientBasicMock.cls-meta.xml
100644 → 100755
Empty file.
Empty file modified src/classes/HttpClientMock.cls
100644 → 100755
Empty file.
Empty file modified src/classes/HttpClientMock.cls-meta.xml
100644 → 100755
Empty file.
Empty file modified src/classes/HttpClientNamedCredentialsMock.cls
100644 → 100755
Empty file.
Empty file modified src/classes/HttpClientNamedCredentialsMock.cls-meta.xml
100644 → 100755
Empty file.
Empty file modified src/classes/HttpClientOAuthMock.cls
100644 → 100755
Empty file.
Empty file modified src/classes/HttpClientOAuthMock.cls-meta.xml
100644 → 100755
Empty file.
27 changes: 27 additions & 0 deletions src/classes/HttpClientProviderAuthProvider.cls
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
public class HttpClientProviderAuthProvider implements HttpClientProviderInterface {
private String authProviderId { get; set; }
private String authProviderType { get; set; }

public HttpClientProviderAuthProvider(String authProviderName) {
AuthProvider[] providers = [
SELECT
Id,
ProviderType
FROM AuthProvider
WHERE FriendlyName =: authProviderName];
if( providers.isEmpty() ){
throw new QueryException('No such Auth Provider '+ authProviderName + ' has been found.');
} else {
this.authProviderId = providers[0].Id;
if(providers[0].ProviderType == 'OpenIdConnect'){
this.authProviderType = 'Open Id Connect';
} else {
this.authProviderType = providers[0].ProviderType;
}
}

}
public String getHeader() {
return 'Bearer ' + Auth.AuthToken.getAccessToken(authProviderId, authProviderType);
}
}
4 changes: 2 additions & 2 deletions src/classes/BasicProvider.cls → src/classes/HttpClientProviderBasic.cls
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
public class BasicProvider implements ICredentialsProvider {
public class HttpClientProviderBasic implements HttpClientProviderInterface {

private String username { get; set; }
private String password { get; set; }

public BasicProvider(String username, String password) {
public HttpClientProviderBasic(String username, String password) {
this.username = username;
this.password = password;
}
Expand Down
File renamed without changes.
12 changes: 12 additions & 0 deletions src/classes/HttpClientProviderBearer.cls
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
public class HttpClientProviderBearer implements HttpClientProviderInterface {

private String token { get; set; }

public HttpClientProviderBearer(String token) {
this.token = token;
}

public String getHeader() {
return 'Bearer ' + token;
}
}
21 changes: 21 additions & 0 deletions src/classes/HttpClientProviderCookie.cls
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/**
* Created by heyoo on 10/07/18.
*/

public class HttpClientProviderCookie implements HttpClientProviderInterface {

private Map<String, String> cookies { get; set; }

public HttpClientProviderCookie(Map<String, String> cookies) {
this.cookies = cookies;
}

public String getHeader() {
String cookie = '';
for(String i: this.cookies.keySet()){
cookie += i+':'+cookies.get(i);
}
return 'Cookie: ' + cookie;
}

}
5 changes: 5 additions & 0 deletions src/classes/HttpClientProviderCookie.cls-meta.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>43.0</apiVersion>
<status>Active</status>
</ApexClass>
3 changes: 3 additions & 0 deletions src/classes/HttpClientProviderInterface.cls
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
public interface HttpClientProviderInterface {
String getHeader();
}
5 changes: 5 additions & 0 deletions src/classes/HttpClientProviderInterface.cls-meta.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>43.0</apiVersion>
<status>Active</status>
</ApexClass>
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
public class NamedCredentialsProvider implements ICredentialsProvider {
public class HttpClientProviderNamedCredentials implements HttpClientProviderInterface {

private String namedCredentials { get; set; }

public NamedCredentialsProvider(String namedCredentialsName) {
public HttpClientProviderNamedCredentials(String namedCredentialsName) {
this.namedCredentials = namedCredentialsName;
}

Expand Down
5 changes: 5 additions & 0 deletions src/classes/HttpClientProviderNamedCredentials.cls-meta.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>43.0</apiVersion>
<status>Active</status>
</ApexClass>
4 changes: 2 additions & 2 deletions src/classes/OAuthProvider.cls → src/classes/HttpClientProviderOAuth.cls
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
public class OAuthProvider implements ICredentialsProvider {
public class HttpClientProviderOAuth implements HttpClientProviderInterface {

public String accessToken { get; set; }
public String authenticationUrl { get; set; }
private Map<String, String> authParameters { get; set; }

public OAuthProvider(String authenticationUrl, Map<String, String> authParameters) {
public HttpClientProviderOAuth(String authenticationUrl, Map<String, String> authParameters) {
this.authenticationUrl = authenticationUrl;
this.authParameters = authParameters;
}
Expand Down
5 changes: 5 additions & 0 deletions src/classes/HttpClientProviderOAuth.cls-meta.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>43.0</apiVersion>
<status>Active</status>
</ApexClass>
15 changes: 15 additions & 0 deletions src/classes/HttpClientProviderSelf.cls
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
public class HttpClientProviderSelf implements HttpClientProviderInterface {
static String[] ref { get; set; }
public String getHeader() {
return 'Bearer ' + ref[0];
}
public String getBaseUrl() {
ref = Page.HttpClientProviderSelf.getContent().toString().split(';');
return ref[1];
}
public String salesforceBaseUrl {
get {
return System.Url.getSalesforceBaseUrl().toExternalForm();
}
}
}
5 changes: 5 additions & 0 deletions src/classes/HttpClientProviderSelf.cls-meta.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>43.0</apiVersion>
<status>Active</status>
</ApexClass>
Loading