Read http post headers - http

Hi I am having trouble I am trying to learn restful services.I created a web service using jax-rs which is shown below
#Path("/users")
public class Welcome {
#POST
#Consumes("text/xml")
#Produces("text/xml")
public Response welcome(String incomingXML){
return Response.status(200).entity("timestamp : " + incomingXML).build();
}
}
I use the following test client to test the service
public class TestService {
public static void main(String args[]) throws ParserConfigurationException, SAXException, IOException {
ClientConfig config = new DefaultClientConfig();
Client client=Client.create(config);
WebResource service=client.resource(getBaseURI());
String urlString = "http://localhost:8080/JaXRSDemo/rest/users";
URL url = new URL( urlString );
HttpURLConnection con = (HttpURLConnection) url.openConnection();
// set up url connection to get retrieve information back
con.setRequestMethod( "POST" );
con.setDoInput( true );
// stuff the Authorization request header
byte[] encodedPassword = ( userName + ":" + password ).getBytes();
con.setRequestProperty( "Authorization",encodedPassword.toString() );
Customer customer=new Customer();
customer.setName("noobstre");
customer.setPin(123455);
ClientResponse response=service.path("rest").path("users").type(MediaType.APPLICATION_XML).post(ClientResponse.class,customer);
System.out.println(" response " + response.getEntity(String.class));
}
private static URI getBaseURI() {
return UriBuilder.fromUri("http://localhost:8080/JaXRSDemo").build();
}
}
I want to use the password in the header at the server side and do a lookup with the database.The problem I am facing is how do I read the headers at the server.

I'm not very familiar with Jax-RS, but you might use the following methods to get the header information you're looking for:
1.) Use #HeaderParam
/**Server side******/
#Path("/users")
public class Welcome {
#POST
#Consumes("text/xml")
#Produces("text/xml")
public Response welcome(String incomingXML, #HeaderParam("Authorization") String authString)
{
//Use authString here
return Response.status(200).entity("timestamp : " + incomingXML).build();
}
}
2.) Use #Context
/**Server side******/
#Path("/users")
public class Welcome {
#POST
#Consumes("text/xml")
#Produces("text/xml")
public Response welcome(String incomingXML, #Context HttpHeaders headers)
{
//Get Authorization Header
String authString = headers.getRequestHeader("Authorization").get(0);
return Response.status(200).entity("timestamp : " + incomingXML).build();
}
}
Hope this helps!

I solved it using Jersey Client
//clientside
ClientConfig config = new DefaultClientConfig();
Client client = Client.create(config);
final String userName = "admin";
final String password = "admin";
String cred = userName + ":" + password;
WebResource service = client.resource(getBaseURI());
Customer customer = new Customer();
customer.setName("noob");
customer.setPin(123455);
ClientResponse response = service.path("rest").path("users")
.accept(MediaType.APPLICATION_XML)
.header("Authorization", cred)
.post(ClientResponse.class, customer);
System.out.println(" response " + response.getEntity(String.class));
At the server side
#Path("/users")
public class Welcome {
#POST
#Consumes(MediaType.APPLICATION_XML)
#Produces(MediaType.APPLICATION_XML)
public Response welcome(String incomingXML, #Context HttpHeaders headers) {
String s = headers.getRequestHeaders().getFirst("authorization");
return Response.status(200).entity("timestamp : " + incomingXML + s)
.build();
}
}

Related

backoffice macro returns 404

i am getting the url 404 not found when loading in a macro.
But then i get in the console a
No HTTP resource was found that matches the request URI 'https://localhost:44351/umbraco/api/prisinformation/produktlista?typ=1&version=0'.No action was found on the controller 'PrisInformation' that matches the name 'produktlista'.
and a
No HTTP resource was found that matches the request URI 'https://localhost:44351/umbraco/api/prisinformation/produktlista?typ=0'.No action was found on the controller 'PrisInformation' that matches the name 'produktlista'.
the code i try to call is this one. no mather how much i try i get this error when calling the macro.
public class PrisInformationController : UmbracoApiController
{
private ILoginService _userService;
private MembershipHelper _membershipHelper;
public PrisInformationController(MembershipHelper membershipHelper, ILoginService userService)
{
_userService = userService;
_membershipHelper = membershipHelper;
}
public void Authorize()
{
if (!_membershipHelper.IsLoggedIn())
{
if (_userService.AddAndOrLoginMember())
{
return;
}
}
throw new HttpException(Request.CreateErrorResponse(HttpStatusCode.Unauthorized, "Page not found").ToString());
}
[HttpGet, HttpPost]
[Route("produktlista/{typ}")]
public HttpResponseMessage Produktlista(int typ = 0, int version = 0)
{
Authorize();
string result = string.Empty;
string apiUrl = ConfigurationManager.AppSettings["ApiUrl"];
try
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(apiUrl + "/databoken/get/produktlista/" + typ + "/" + version);
request.Method = WebRequestMethods.Http.Get;
request.Accept = "application/json";
var response = request.GetResponse();
string s = string.Empty;
using (var sr = new StreamReader(response.GetResponseStream()))
{
result = sr.ReadToEnd();
}
}
I read it as your Produktlista method has a route defined that requires you to do /umbraco/api/prisinformation/produktlista/1 where 1 is typ, instead of ?typ=1. I could totally be wrong though, but maybe try removing the custom Route definition and see if that helps?
https://our.umbraco.com/Documentation/Reference/Routing/Umbraco-API-Controllers/index-v8
On another note you can change your controller to be of type UmbracoAuthorizedApiController which will do the backoffice auth check for you. Just note that it will change the standard route to be /umbraco/backoffice/api/... instead.

Gmail fails to respond with MailKit

I'm working in ASP.NET Core and using MailKit for email functionality. The method I've previously used is no longer working.
I have an SmtpOptions.cs class:
public class SmtpOptions
{
public string Server { get; set; } = "smtp.gmail.com"; //Gmail limited to 2000 emails per day
public int Port { get; set; } = 465; //default for SSL using GMail
public string User { get; set; } = "myEmail#gmail.com"; //must match server domain
public string Password { get; set; } = "myPwd";
public bool UseSsl { get; set; } = true; //gmail requires SSL
public bool RequiresAuthentication { get; set; } = true; //gmail requires authentication
public string PreferredEncoding { get; set; } = string.Empty;
}
and EmailSender.cs class:
public class EmailSender
{
public EmailSender()
{
}
public async Task SendEmailAsync(
SmtpOptions smtpOptions,
string to,
string from,
string subject,
string plainTextMessage,
string htmlMessage,
string replyTo = null)
{
if (string.IsNullOrWhiteSpace(to))
{
throw new ArgumentException("no to address provided");
}
if (string.IsNullOrWhiteSpace(from))
{
throw new ArgumentException("no from address provided");
}
if (string.IsNullOrWhiteSpace(subject))
{
throw new ArgumentException("no subject provided");
}
var hasPlainText = !string.IsNullOrWhiteSpace(plainTextMessage);
var hasHtml = !string.IsNullOrWhiteSpace(htmlMessage);
if (!hasPlainText && !hasHtml)
{
throw new ArgumentException("no message provided");
}
var m = new MimeMessage();
m.From.Add(new MailboxAddress("", from));
if (!string.IsNullOrWhiteSpace(replyTo))
{
m.ReplyTo.Add(new MailboxAddress("", replyTo));
}
m.To.Add(new MailboxAddress("", to));
m.Subject = subject;
//m.Importance = MessageImportance.Normal;
//Header h = new Header(HeaderId.Precedence, "Bulk");
//m.Headers.Add()
BodyBuilder bodyBuilder = new BodyBuilder();
if (hasPlainText)
{
bodyBuilder.TextBody = plainTextMessage;
}
if (hasHtml)
{
bodyBuilder.HtmlBody = htmlMessage;
}
m.Body = bodyBuilder.ToMessageBody();
using (var client = new SmtpClient())
{
await client.ConnectAsync(
smtpOptions.Server,
smtpOptions.Port,
smtpOptions.UseSsl)
.ConfigureAwait(false);
// Note: since we don't have an OAuth2 token, disable
// the XOAUTH2 authentication mechanism.
client.AuthenticationMechanisms.Remove("XOAUTH2");
// Note: only needed if the SMTP server requires authentication
if (smtpOptions.RequiresAuthentication)
{
await client.AuthenticateAsync(smtpOptions.User, smtpOptions.Password)
.ConfigureAwait(false);
}
await client.SendAsync(m).ConfigureAwait(false);
await client.DisconnectAsync(true).ConfigureAwait(false);
}
}
public async Task SendMultipleEmailAsync(
SmtpOptions smtpOptions,
string toCsv,
string from,
string subject,
string plainTextMessage,
string htmlMessage)
{
if (string.IsNullOrWhiteSpace(toCsv))
{
throw new ArgumentException("no to addresses provided");
}
if (string.IsNullOrWhiteSpace(from))
{
throw new ArgumentException("no from address provided");
}
if (string.IsNullOrWhiteSpace(subject))
{
throw new ArgumentException("no subject provided");
}
var hasPlainText = !string.IsNullOrWhiteSpace(plainTextMessage);
var hasHtml = !string.IsNullOrWhiteSpace(htmlMessage);
if (!hasPlainText && !hasHtml)
{
throw new ArgumentException("no message provided");
}
var m = new MimeMessage();
m.From.Add(new MailboxAddress("", from));
string[] adrs = toCsv.Split(',');
foreach (string item in adrs)
{
if (!string.IsNullOrEmpty(item)) { m.To.Add(new MailboxAddress("", item)); ; }
}
m.Subject = subject;
m.Importance = MessageImportance.High;
BodyBuilder bodyBuilder = new BodyBuilder();
if (hasPlainText)
{
bodyBuilder.TextBody = plainTextMessage;
}
if (hasHtml)
{
bodyBuilder.HtmlBody = htmlMessage;
}
m.Body = bodyBuilder.ToMessageBody();
using (var client = new SmtpClient())
{
await client.ConnectAsync(
smtpOptions.Server,
smtpOptions.Port,
smtpOptions.UseSsl).ConfigureAwait(false);
// Note: since we don't have an OAuth2 token, disable
// the XOAUTH2 authentication mechanism.
client.AuthenticationMechanisms.Remove("XOAUTH2");
// Note: only needed if the SMTP server requires authentication
if (smtpOptions.RequiresAuthentication)
{
await client.AuthenticateAsync(
smtpOptions.User,
smtpOptions.Password).ConfigureAwait(false);
}
await client.SendAsync(m).ConfigureAwait(false);
await client.DisconnectAsync(true).ConfigureAwait(false);
}
}
}
That are used in a function call:
public async void ContactMessage(string title, string message, string toEmail)
{
string thisMessage = "No Message Provided";
if (!String.IsNullOrEmpty(message)) { thisMessage = message; } //in case empty form
string thisTitle = title;
//create email objects
EmailSender emailSender = new EmailSender();
SmtpOptions smtpOptions = new SmtpOptions(); //default settings ok
string fromEmail = smtpOptions.User;
string subjectLine = "Message Title";
await emailSender.SendEmailAsync(smtpOptions, toEmail, fromEmail, subjectLine, thisMessage, "");
}
As stated, this method has worked before but now I'm getting a failure of Gmail to respond. I've checked and have IMAP and POP enabled.
The specific exception reads:
"System.Net.Internals.SocketExceptionFactory.ExtendedSocketE‌​xception: 'A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond'"
This code has not been deployed but causes this error in the test environment. Moving to a differently firewalled system causes the error "Mailkit.Security.Authentication; MailKit authentication is too weak"
Testing with Yahoo! smtp allows the above code to work so it seems like the compatibility between Mailkit and Gmail has changed. What is the appropriate Mailkit configuration for using Gmail?
The email account settings were not configured to allow use of less-secure apps. The two solutions are:
1) Obtain OAuth 2.0 credentials within the EmailSender.cs class, or
2) Change email account settings to allow less secure apps
There are more details at:
How to send email by using MailKit?
Generally, when you get an AuthenticationException saying that the AUTH mechanism was too weak, it means that the client tried to use the PLAIN or LOGIN mechanisms and the server only allows those mechanisms to be used over SSL.
Make sure you are connecting on port 465 with SSL enabled or on port 587 with SecureSocketOptions.StartTls as the third argument.

Basic Authentication with Retrofit

I am trying to build a client for a REST API using Retrofit. The API uses basic auth and I have been unable to authenticate using Retrofit.
I tested the API using the curl below and it works as expected
curl -H "Accept: application/json" -H "Content-type: application/json" -X POST -d '{some_json}' -u api_key: https://apitest.com/api/v1/customers
Below is the Retrofit client
public interface UserService {
String HOST = "https://apitest.com";
public static OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
public static Retrofit.Builder builder =
new Retrofit.Builder()
.baseUrl(HOST)
.addConverterFactory(GsonConverterFactory.create());
/*
* CREATE/UPDATE User
*/
#POST("api/v1/customers")
Call<UserAPIResponse> userUpdate(#Body UserUpdateRequest userUpdateRequest);
static UserService newInstance(String userAPIKey) {
String credentials = userAPIKey + ":";
final String basic = "Basic "+ Base64.encodeBase64(credentials.getBytes());
httpClient.addInterceptor(new Interceptor() {
#Override
public Response intercept(Interceptor.Chain chain) throws IOException {
Request original = chain.request();
Request.Builder requestBuilder = original.newBuilder()
.header("Authorization", basic);
requestBuilder.header("Accept", "application/json");
requestBuilder.method(original.method(),original.body());
Request request = requestBuilder.build();
return chain.proceed(request);
}
});
OkHttpClient client = httpClient.build();
Retrofit retrofit = builder.client(client).build();
return retrofit.create(BlueshiftUserService.class);
}
When I call updateUser on the UserService
Response<UserAPIResponse> response = UserService.userUpdate(userUpdateRequest).execute();
The response.code is 401 (unauthorized/authentication failed)
The curl command with -u and the same credentials works as expected.
The issue was with the credentials encoding. I wasnt sending it as string.
byte[] encodedAuth= Base64.encodeBase64(credentials.getBytes());
final String basic = "Basic " + new String(encodedAuth);
use these libraries in Gradle file
compile 'com.squareup.retrofit:retrofit:1.9.0'
compile 'com.squareup.okhttp:okhttp:2.3.0'
compile 'com.cookpad.android.rxt4a:rxt4a:0.9.0'
compile 'io.reactivex:rxjava:1.0.12'
and put this classes in your project
public class ServiceGenerator {
private static final String TAG = erviceGenerator.class.getSimpleName();
public static final int READ_TIMEOUT = 10000;
public static final int CONNECT_TIMEOUT = 100000;
// No need to instantiate this class.
private ServiceGenerator(){}
public static <S> S createService(Class<S> serviceClass, String
endpoint) {
// Call basic auth generator method without user and pass
return createService(serviceClass, endpoint, null, null); }
public static <S> S createService(Class<S> serviceClass, String
endpoint, String username, String password) {
OkHttpClient okHttpClient = new OkHttpClient();
okHttpClient.setReadTimeout(READ_TIMEOUT, TimeUnit.SECONDS);
okHttpClient.setConnectTimeout(CONNECT_TIMEOUT, TimeUnit.SECONDS);
// Set endpoint url and use OkHTTP as HTTP client
RestAdapter.Builder builder = new RestAdapter.Builder()
.setEndpoint(endpoint)
.setConverter(new GsonConverter(new Gson()))
.setClient(new OkClient(okHttpClient));
if (username != null && password != null) {
// Concatenate username and password with colon for authentication
final String credentials = username + ":" + password;
builder.setRequestInterceptor(new RequestInterceptor() {
#Override
public void intercept(RequestFacade request) {
// Create Base64 encoded string
String string = "Basic " + Base64.encodeToString(credentials.getBytes(), Base64.NO_WRAP);
request.addHeader("Authorization", string);
request.addHeader("Accept", "application/json");
}
});
}
RestAdapter adapter = builder.build();
return adapter.create(serviceClass); } }
and this interface
public class TodolyClient {
private static final String TAG = TodolyClient.class.getSimpleName();
public static final String ENDPOINT = "your base URL";
public interface TodolyService {
#GET("/wp-json/wc/v2/products")(your remaining url)
Observable<Object> isAuthenticated();
}
}
and call the below method in your main activity
private void createProject() {
final TodolyClient.TodolyService service =ServiceGenerator.createService(
TodolyClient.TodolyService.class, TodolyClient.ENDPOINT, "your user name",
"your password");
Observable<Object> observable = service.isAuthenticated();
AndroidCompositeSubscription compositeSubscription = new AndroidCompositeSubscription();
observable
.lift(new OperatorAddToCompositeSubscription<Object>(compositeSubscription))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<Object>() {
#Override
public void onNext(Object project) {
android.util.Log.d(TAG, "onNext: "+project.toString());
}
#Override
public void onCompleted() {
android.util.Log.d(TAG, "onNext:commm " );
}
#Override
public void onError(Throwable e) {
android.util.Log.d(TAG, "onNext: eeeeeeeee"+e.getMessage());
}
});
}
This is so far the easiest method i have ever tried for "Basic Authentication".
Use the below code to generate the auth header (API/Repository class), You can add any character set for encoding as the third parameter here.
var basic = Credentials.basic("YOUR_USERNAME", "YOUR_PASSWORD")
Pass this as header to the webservice call (API/Repository class)
var retrofitCall = myWebservice.getNewsFeed(basic)
Add the basic header as parameter (Retrofit Webservice interface class)
#GET("newsfeed/daily")
fun getNewsFeed(#Header("Authorization") h1:String):Call<NewsFeedResponse>
Sorry, my code is in Kotlin, but can be easily translated to Java.
References: https://mobikul.com/basic-authentication-retrofit-android/

Agent servlet communication

I just started to use Jade and I would like to know if it is possible to send a message from an agent to a servlet using JadeGateway, I have already managed to send a message from a servlet to an agent, but I want that agent to send back a reply and nothing seems to work for me.
Here is the doPost method of my servlet:
String champ = request.getParameter("action");
try {
JadeGateway.execute(new OneShotBehaviour() {
#Override
public void action() {
out.println("action");
final ACLMessage msg = new ACLMessage(ACLMessage.REQUEST);
AID theAgent = new AID("Agent47", false);
msg.addReceiver(theAgent);
msg.setConversationId("Agent servlet communication");
msg.setContent(champ);
myAgent.send(msg);
ACLMessage res = myAgent.receive();
if (res != null) {
System.out.println(res.getContent());
}
}
});
The servlet sends the data entered by the user in a jsp page to the agent.
Here is the code of the agent:
//The cyclic behaviour i added to the agent
public class ProcessExternalRequests extends CyclicBehaviour {
private MessageTemplate mt;
#Override
public void action() {
mt = MessageTemplate.MatchConversationId("Agent servlet communication");
ACLMessage msg = myAgent.receive(mt);
if(msg!=null){
if(msg.getPerformative()==ACLMessage.REQUEST){
String content = msg.getContent();
System.out.println("Agent " + myAgent.getAID().getLocalName() + " Content = " + content);
//Response
ACLMessage res = new ACLMessage(ACLMessage.CONFIRM);
res.addReceiver(msg.getSender());
res.setContent("Bien reçu!");
myAgent.send(res);
}
}else{
block();
}
My problem is that the agent won't send a message back to the servlet. What should I do?

RESTeasy back-end - Restlet front-end : response entity null

I have some REST services on my server (Jetty, RESTeasy) and a GWT client.
I choosed to use Restlet-GWT module on the front end.
I made a JSE client (RESTeasy client) and my service is well called (i see SQL trace in the log of Jetty server) and i get an xml response.
Then i tried from GWT with Restlet. The web service is called (Jetty log) but i have a null response.
Web service (Back end):
#GET
#Path("/getArt/{id}")
#Produces("application/xml")
public Art getArt(#PathParam("id")int id){
Art art= artDAO.findById(id);
return art;
}
Front-end GWT :
public class Front_End implements EntryPoint {
/**
* This is the entry point method.
*/
public void onModuleLoad() {
final Client client = new Client(Protocol.HTTP);
client.get("http://localhost:8080/rest/service/getArt/1", new Callback() {
#Override
public void onEvent(Request request, Response response) {
System.out.println("Reponse : " + response.getEntity().getText());
}
});
}
RESTeasy client working :
public Object test(int id){
try {
ClientRequest request = new ClientRequest("http://localhost:8080/rest/service/getArt/"+id);
request.accept("application/xml");
ClientResponse<String> response = request.get(String.class);
if (response.getStatus() == 200)
{
Unmarshaller un = jc.createUnmarshaller();
Object o = un.unmarshal(new StringReader(response.getEntity()));
return o;
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
Are RESTeasy and Restlet "compatible" ? Should i use Restlet in the back end instead of RESTeasy ? What am i missing ?
Thx in advance
It was a SOP issue.
My server was running on port 8080, and GWT on port 8888.
I used a proxy (put it in your /war in the client side) :
proxy.jsp
<%#page import="javax.naming.Context"%>
<%#page import="javax.naming.InitialContext"%><%#page session="false"%>
<%#page import="java.net.*,java.io.*" %>
<%
try {
String reqUrl = request.getQueryString();
URL url = new URL(reqUrl.substring(4));
HttpURLConnection con = (HttpURLConnection)url.openConnection();
con.setDoOutput(true);
con.setRequestMethod(request.getMethod());
int clength = request.getContentLength();
if (clength > 0) {
con.setDoInput(true);
byte[] idata = new byte[clength];
request.getInputStream().read(idata,0,clength);
con.getOutputStream().write(idata,0,clength);
}
response.setContentType(con.getContentType());
BufferedReader rd = new BufferedReader(new InputStreamReader(con.getInputStream()));
String line;
while ((line = rd.readLine()) != null) {
out.println(line);
}
rd.close();
} catch (Exception e) {
e.printStackTrace();
response.setStatus(500);
}
%>
then in your class where you make the call, your url becomes :
String url ="proxy.jsp?url=" + URL.encode("http://localhost:8080/rest/service/getArt/1");
There is another way to solve it, check https://developers.google.com/web-toolkit/doc/1.6/tutorial/Xsite

Resources