Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
New feature : capability to send HTTP request (e.g. to Web service)
- Loading branch information
1 parent
14dee4e
commit e2585a2
Showing
6 changed files
with
354 additions
and
0 deletions.
There are no files selected for viewing
56 changes: 56 additions & 0 deletions
56
ummisco.gama.network/models/Network/2 Available protocols/HTTP Request/HTTP GET.gaml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
/** | ||
* Name: HTTPGET | ||
* Based on the internal empty template. | ||
* Author: benoitgaudou | ||
* Tags: | ||
*/ | ||
|
||
|
||
model HTTPGET | ||
|
||
global { | ||
int port <- 443; // for HTPP : 80 http, for HTTPS : 443 | ||
string url <- "https://openlibrary.org"; | ||
|
||
init { | ||
create NetworkingAgent number: 1 { | ||
do connect to: url protocol: "http" port: port raw: true; | ||
} | ||
} | ||
|
||
} | ||
|
||
species NetworkingAgent skills:[network] { | ||
|
||
reflex send when: cycle = 0 { | ||
write "sending message "; | ||
do send to: "/search/authors.json?q=j%20k%20rowling" contents: ["GET"]; | ||
} | ||
|
||
reflex get_message { | ||
loop while:has_more_message() | ||
{ | ||
//read a message | ||
message mess <- fetch_message(); | ||
//display the message | ||
write name + " fecth this message: " + mess.contents; | ||
write sample(map(mess.contents)["CODE"]); | ||
write sample(map(mess.contents)["BODY"]); | ||
write sample(map(mess.contents)["HEADERS"]); | ||
} | ||
|
||
} | ||
|
||
|
||
aspect default { | ||
draw circle(1) color: #red border: #black; | ||
} | ||
} | ||
|
||
experiment Server_testdd type: gui { | ||
output { | ||
display d { | ||
species NetworkingAgent; | ||
} | ||
} | ||
} |
60 changes: 60 additions & 0 deletions
60
ummisco.gama.network/models/Network/2 Available protocols/HTTP Request/HTTP POST.gaml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
/** | ||
* Name: HTTPGET | ||
* Based on the internal empty template. | ||
* Author: benoitgaudou | ||
* Tags: | ||
*/ | ||
|
||
|
||
model HTTPGET | ||
|
||
global { | ||
int port <- 8989; // for HTPP : 80 http, for HTTPS : 443 | ||
string url <- "localhost"; | ||
|
||
init { | ||
create NetworkingAgent number: 1 { | ||
do connect to: url protocol: "http" port: port raw: true; | ||
} | ||
} | ||
|
||
} | ||
|
||
species NetworkingAgent skills:[network] { | ||
|
||
reflex send when: cycle = 0 { | ||
write "sending message "; | ||
|
||
// do send to: "/api/user/" contents: ["POST",map(["toto"::34,"titi"::12]), map(["Content-Type"::"application/json"])]; | ||
// do send to: "/api/user/" contents: ["PUT",map(["toto"::34,"titi"::12]), map(["Content-Type"::"application/json"])]; | ||
do send to: "/api/user/" contents: ["DELETE"]; | ||
|
||
} | ||
|
||
reflex get_message { | ||
loop while:has_more_message() | ||
{ | ||
//read a message | ||
message mess <- fetch_message(); | ||
//display the message | ||
write name + " fecth this message: " + mess.contents; | ||
write sample(map(mess.contents)["CODE"]); | ||
write sample(map(mess.contents)["BODY"]); | ||
write sample(map(mess.contents)["HEADERS"]); | ||
} | ||
|
||
} | ||
|
||
|
||
aspect default { | ||
draw circle(1) color: #red border: #black; | ||
} | ||
} | ||
|
||
experiment Server_testdd type: gui { | ||
output { | ||
display d { | ||
species NetworkingAgent; | ||
} | ||
} | ||
} |
172 changes: 172 additions & 0 deletions
172
ummisco.gama.network/src/ummisco/gama/network/httprequest/HTTPRequestConnector.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,172 @@ | ||
package ummisco.gama.network.httprequest; | ||
|
||
import java.io.IOException; | ||
import java.net.URI; | ||
import java.net.URISyntaxException; | ||
import java.net.http.HttpClient; | ||
import java.net.http.HttpRequest; | ||
import java.net.http.HttpResponse; | ||
import java.net.http.HttpRequest.Builder; | ||
|
||
import msi.gama.extensions.messaging.GamaMailbox; | ||
import msi.gama.extensions.messaging.GamaMessage; | ||
import msi.gama.extensions.messaging.MessagingSkill; | ||
import msi.gama.metamodel.agent.IAgent; | ||
import msi.gama.runtime.IScope; | ||
import msi.gama.util.GamaList; | ||
import msi.gama.util.IMap; | ||
import msi.gama.util.file.json.Jsoner; | ||
import ummisco.gama.network.common.Connector; | ||
import ummisco.gama.network.common.GamaNetworkException; | ||
import ummisco.gama.network.common.socket.SocketService; | ||
import ummisco.gama.network.httprequest.utils.Utils; | ||
|
||
public class HTTPRequestConnector extends Connector { | ||
|
||
/** The timeout. */ | ||
public static Integer DEFAULT_TIMEOUT = 5000; | ||
|
||
/** The default host. */ | ||
public static String DEFAULT_HOST = "localhost"; | ||
|
||
/** The default port. */ | ||
public static String DEFAULT_PORT = "80"; | ||
|
||
|
||
/** The ss thread. */ | ||
// MultiThreadedArduinoReceiver ssThread; | ||
|
||
String host; | ||
String port; | ||
|
||
// | ||
private HttpRequest request; | ||
|
||
/** | ||
* Instantiates a new HTTPRequest connector. | ||
* | ||
* @param scope the scope | ||
*/ | ||
public HTTPRequestConnector(final IScope scope) { | ||
} | ||
|
||
@Override | ||
protected void connectToServer(IAgent agent) throws GamaNetworkException { | ||
String host_tmp = this.getConfigurationParameter(SERVER_URL); | ||
String port_tmp = this.getConfigurationParameter(SERVER_PORT); | ||
|
||
host = host_tmp == null ? DEFAULT_HOST : host_tmp; | ||
port = port_tmp == null ? DEFAULT_PORT : port_tmp; | ||
} | ||
|
||
@Override | ||
protected boolean isAlive(IAgent agent) throws GamaNetworkException { | ||
// TODO Auto-generated method stub | ||
return false; | ||
} | ||
|
||
@Override | ||
protected void subscribeToGroup(IAgent agt, String boxName) throws GamaNetworkException { | ||
// TODO Auto-generated method stub | ||
|
||
} | ||
|
||
@Override | ||
protected void unsubscribeGroup(IAgent agt, String boxName) throws GamaNetworkException { | ||
// TODO Auto-generated method stub | ||
|
||
} | ||
|
||
@Override | ||
protected void releaseConnection(IScope scope) throws GamaNetworkException { | ||
// TODO Auto-generated method stub | ||
|
||
} | ||
|
||
@Override | ||
public void send(final IAgent sender, final String receiver, final GamaMessage content) { | ||
Object cont = content.getContents(sender.getScope()); | ||
try { | ||
if(cont instanceof GamaList) { | ||
URI uri = null; | ||
try { | ||
uri = Utils.buildURI(host,""+port,receiver); | ||
} catch (URISyntaxException e) { | ||
e.printStackTrace(); | ||
} | ||
Builder requestBuilder = HttpRequest.newBuilder().uri(uri); | ||
|
||
// Management of the content. A list [method,body,headers] or [method] are expected | ||
GamaList listContent = (GamaList) cont; | ||
String method = (String) listContent.get(0); | ||
String jsonBody = (listContent.size() > 1) ? Jsoner.serialize(listContent.get(1)) : ""; | ||
IMap<String,String> header = (listContent.size() > 2) ? (IMap<String,String>) listContent.get(2) : null; | ||
|
||
if(header != null) { | ||
for(String key : header.keySet()) { | ||
requestBuilder.header(key, header.get(key)); | ||
} | ||
} | ||
|
||
switch(method) { | ||
case "GET": | ||
request = requestBuilder.GET().build(); | ||
break; | ||
case "POST": | ||
request = requestBuilder.POST(HttpRequest.BodyPublishers.ofString(jsonBody)).build(); | ||
break; | ||
case "PUT": | ||
request = requestBuilder.PUT(HttpRequest.BodyPublishers.ofString(jsonBody)).build(); | ||
break; | ||
case "DELETE": | ||
request = requestBuilder.DELETE().build(); | ||
break; | ||
default: | ||
throw GamaNetworkException.cannotSendMessage(null, "Bad HTTP action"); | ||
} | ||
|
||
this.sendMessage(sender, receiver, jsonBody); | ||
|
||
} else { | ||
throw GamaNetworkException.cannotSendMessage(null, "The content expected to be sent is well formatted, a list [method,body,headers] is expected."); | ||
} | ||
} catch (Exception e) { | ||
e.printStackTrace(); | ||
} | ||
} | ||
|
||
|
||
@Override | ||
protected void sendMessage(IAgent sender, String receiver, String content) throws GamaNetworkException { | ||
|
||
try { | ||
|
||
HttpResponse<String> response = HttpClient.newHttpClient() | ||
.send(request, HttpResponse.BodyHandlers.ofString()); | ||
|
||
// Manage the response of the request | ||
IMap<String,Object> responseMap = Utils.formatResponse(response); | ||
|
||
@SuppressWarnings ("unchecked") | ||
GamaMailbox<GamaMessage> mailbox = | ||
(GamaMailbox<GamaMessage>) sender.getAttribute(MessagingSkill.MAILBOX_ATTRIBUTE); | ||
if (mailbox == null) { | ||
mailbox = new GamaMailbox<>(); | ||
sender.setAttribute(MessagingSkill.MAILBOX_ATTRIBUTE, mailbox); | ||
} | ||
|
||
GamaMessage msg = new GamaMessage(sender.getScope(), "HTTP", sender.getName(), responseMap); | ||
|
||
mailbox.add(msg); | ||
|
||
} catch (IOException | InterruptedException e) { | ||
e.printStackTrace(); | ||
} | ||
} | ||
|
||
@Override | ||
public SocketService getSocketService() { | ||
return null; | ||
} | ||
|
||
} |
58 changes: 58 additions & 0 deletions
58
ummisco.gama.network/src/ummisco/gama/network/httprequest/utils/Utils.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
package ummisco.gama.network.httprequest.utils; | ||
|
||
import java.net.URI; | ||
import java.net.URISyntaxException; | ||
import java.net.http.HttpResponse; | ||
import java.util.List; | ||
import java.util.Map; | ||
|
||
import msi.gama.runtime.IScope; | ||
import msi.gama.util.GamaMapFactory; | ||
import msi.gama.util.IList; | ||
import msi.gama.util.IMap; | ||
import msi.gama.util.file.json.DeserializationException; | ||
import msi.gama.util.file.json.Jsoner; | ||
import msi.gaml.types.Types; | ||
|
||
public class Utils { | ||
public static URI buildURI(final String host, final String port, final String url) throws URISyntaxException { | ||
String uri = "" ; | ||
String local_port = ( (port != null) ? (":"+port) : ""); | ||
|
||
if(host.startsWith("http://") || host.startsWith("https://")) { | ||
uri = host + local_port + url; | ||
} else { | ||
uri = "http://"+host + local_port + url; | ||
} | ||
|
||
return new URI(uri);//URLEncoder.encode(uri, StandardCharsets.UTF_8)); | ||
} | ||
|
||
public static IList parseBODY(final IScope scope, final String body) { | ||
// TODO Transform lee boy en map/list si response en JSON | ||
|
||
return null; | ||
} | ||
|
||
|
||
public static IMap<String,Object> formatResponse(HttpResponse<String> response){ | ||
IMap<String,Object> responseMap = null; | ||
|
||
try { | ||
responseMap = GamaMapFactory.create(); | ||
|
||
responseMap.put("CODE", response.statusCode()); | ||
|
||
Object jsonBody = ("".equals(response.body())) ? "" : Jsoner.deserialize(response.body()); | ||
responseMap.put("BODY", jsonBody); | ||
|
||
IMap<String, List<String>> mapHeaders = GamaMapFactory.wrap(Types.STRING, Types.STRING, false, (Map<String,List<String>>) response.headers().map()); | ||
responseMap.put("HEADERS",mapHeaders); | ||
} catch (DeserializationException e) { | ||
e.printStackTrace(); | ||
} | ||
|
||
return responseMap; | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters