Start dart application from Server and load elements - dart

I'm new in dart's programming and I'm building a dart app and I would like to start it from the server side. Like loading my homepage when I enter the url of my webpage.
On my server side I have this code that I took from tutorials from dart's webpage:
var server;
try{
server = await HttpServer.bind(InternetAddress.LOOPBACK_IP_V6, 4040);
}catch(e){
print("Couldn't bind to port 4044: $e");
exit(-1);
}
await for(HttpRequest req in server){
var file = new File('index.html');
if(await file.exists()){
print("Serving index.html.");
req.response.headers.contentType = ContentType.HTML;
try{
await file.openRead().pipe(req.response);
}catch(e){
print("Couldn't read file: $e");
exit(-1);
}
}else{
print("Couldn't open index.html");
req.response..statusCode = HttpStatus.NOT_FOUND..close();
}
}
But now my problem is about the client side, my elements are not loading, like css, images, etc.
You can see the appearance here
I think that I need to set something at my server side to load that. What is it?

Using the core dart:io methods for serving files is often not the easiest way. Take a look at shelf, f.e. It's a really neat framework for creating server applications that has a lot of plugins and extensions for middleware etc.
In your case, it seems like you just want to serve static content. I'd suggest you use shelf_static. It would go like this:
import 'package:shelf/shelf_io.dart' as io;
import 'package:shelf_static/shelf_static.dart';
void main() {
var handler = createStaticHandler('your-web-directory/',
defaultDocument: 'index.html');
io.serve(handler, InternetAddress.LOOPBACK_IP_V6, 4040);
}

Related

How to get Redis key values on Server side Dart with Angel

Having moved my mobile app development to Flutter I am now in the process of experimenting with using Dart as my main server side language. The productivity benefits in using a single coding language in both the app and on the server are considerable. To that end I have set up a server with an Nginx front end which proxies all dynamic web requests to an Angel/Dart server.
Angel is a remarkably well written package and I had a working server written up in no time at all. However, in order to have a fully functional backend I need to be able to use both Redis and PostgreSQL from within my server side Dart code. I am using the resp_client package to access Redis. The issue I have run into is with the fact that RespCommand.get is asynchronous. With my newbie knowledge of both Dart and Angel I am unable to find a way to acquire a Redis key value via RespCommand.get in an Angel route handler and then somehow use that value in the response it returns.
My entire Dart backend server code is shown below
import 'package:angel_framework/angel_framework.dart';
import 'package:angel_framework/http.dart';
import 'package:postgres/postgres.dart';
import 'package:resp_client/resp_client.dart';
import 'package:resp_client/resp_commands.dart';
class DartWeb
{
static Angel angel;
static AngelHttp http;
static RespCommands redis;
static PostgreSQLConnection db;
static init() async
{
angel = Angel();
http = AngelHttp(angel);
angel.get('/',rootRoute);
await prepareRedis();
await http.startServer('localhost',3000);
}
static prepareRedis() async
{
RespServerConnection rsc = await connectSocket('localhost');
RespClient client = RespClient(rsc);
redis = RespCommands(client);
}
static preparePostgres() async
{
db = new PostgreSQLConnection('serverurl',portNo,'database',username:'user',password:'password');
await db.open();
}
static void rootRoute(RequestContext req,ResponseContext res)
{
try
{
await redis.set('test','foobar',expire:Duration(seconds:10));
String testVal = await redis.get('test');
res.write('Done $testVal');
} catch(e) {res.write('++ $e ++');}
}
}
main() async {await DartWeb.init();}
If I start up this server and then access it through my web browser I end up with a 502 Bad Gateway message. Not surprising. dart2native main.dart -o mainCompiled returns the error await can only be used in async... message.
So I tried instead
try
{
res.write('Before');
redis.set('test','foobar',expire:Duration(seconds:10)).then((bool done)
{
res.write('DONE $done');
});
res.write('After');
} catch(e) {res.write('++ $e ++');}
which simply printed out BeforeAfter in my browser with the DONE bit never showing up although a quick test via redis-cli shows that the key test had in fact been created.
My knowledge of both Dart and Angel is still in its infancy so I guess I am doing something incorrectly here. Shorn of all the detail my questions are essentially these -
how do I call and get the result from async methods in an Angel route dispatcher?
given that I am editing my Dart code in VSCode on my local Windows machine which accesses the relevant dart files on my Ubuntu server I loose the benefits of error reporting provided by the VSCode Dart plugin. dart2native, as I have used here, helps out but it would be nicer if I could somehow get a running error report within VSCode as I do when building Flutter apps locally. How can I accomplish this - if at all possible?
It turns out that Dart/Angel does not impose excessively strict constraints on the signature of a route handler. So you can quite safely declare a route handler like this one
static Future<void> rootRoute(RequestContext req,ResponseContext res) async
{
try
{
res.write('!! Before ');
await redis.set('test','foobar',expire:Duration(seconds:10));
String test = await redis.get('test');
res.write('After $test !!');
} catch(e) {res.write('++ $e ++');}
}
With the route simply returning a Future we can now safely do anything we like there - including calling other asynchronous methods: in this instance to fetch a Redis key value.

Configure bitbucket plugin to avoid hardcoding of secure variable

I have developed an Atlasian Bitbucket plugin which globally listens for push/PR and send repository details to databases using REST API.
I need to configure REST API URL and credential so that my plugin can make an API call. Currently I have hardcoded REST API URL and credential in my plugin properties file. Which I don't like because every time if I need to create a package to target my test environment or production, I have to change. Also, I don't like to keep credentials in the source code.
What is the best way to add configuration screen in the bitbucket plugin? I would like to have form for URL, username and password (once I installed the plugin) and update the storage in Bitbucket only once. If I need to restart my bitbucket, I do not want to lose saved data.
I tried to search on how to configure a bitbucket plugin, however I could not find an easy way. I do see multiple approaches, for example to add "Configure" button which will open a servelet to take user input. Seems very cryptic to me. Also, I see so many recommendations for template, for example velocity, soy etc which confused me a lot.
Since I am new to plugin development therefore not able to explore. Looking for some help.
I have solution for this case:
From pom.xml please add more library:
<dependency>
<groupId>com.atlassian.plugins</groupId>
<artifactId>atlassian-plugins-core</artifactId>
<version>5.0.0</version>
<scope>provided</scope>
</dependency>
Create new abc-server.properties on resources/ folder with following content:
server.username=YOUR_USERNAME
server.password=YOUR_PASSWORD
Get value from abc-server.properties on service class as the following:
import com.atlassian.plugin.util.ClassLoaderUtils;
...
final Properties p = new Properties();
final InputStream is = ClassLoaderUtils.getResourceAsStream("abc-server.properties", this.getClass());
try {
if (is != null) {
p.load(is);
String username = p.getProperty("server.username");
String password = p.getProperty("server.password");
}
} catch (IOException e) {
e.printStackTrace();
}
Please try to implement it. Thanks!
One possibility for a simple configuration file, is to read somefile.properties from the Bitbucket home directory, this way the config file will survive application updates.
Create somefile.properties in BITBUCKET_HOME
server.username=YOUR_USERNAME
server.password=YOUR_PASSWORD
Read the properties in your plugin class like this
// imports
import com.atlassian.bitbucket.server.StorageService;
import com.atlassian.plugin.spring.scanner.annotation.imports.ComponentImport;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
private final StorageService storageService;
// StorageService injected via constructor injection
public SomePlugin(#ComponentImport final StorageService storageService) {
this.storageService = storageService;
}
Properties p = new Properties();
File file = new File(storageService.getHomeDir().toString(), "somefile.properties");
FileInputStream fileInputStream;
try {
fileInputStream = new FileInputStream(file);
p.load(fileInputStream);
String username = p.getProperty("server.username");
String password = p.getProperty("server.password");
} catch (IOException e) {
//handle exception
}

Clear url in browser window using Java code

I am using navigate().to() method to navigate but new url is getting appended to old url as below, after executing navigate.to function thus resulting in 404 error
https://www.google.co.in/www.yahoo.co.in
Can anyone please help how should I get this to work?
public static void main(String[] args) throws InterruptedException {
WebDriver fd = new FirefoxDriver();
fd.get("http://www.google.co.in");
Thread.sleep(3000);
fd.navigate().to("www.yahoo.co.in");
}
}
I'm not sure how to use navigate().to() but this an alternative solution.
import java.awt.Desktop;
import java.net.URI;
....
try {
Desktop d = Desktop.getDesktop();
d.browse(new URI("http://www.google.co.in"));
Thread.sleep(3000);
d.browse(new URI("www.yahoo.co.in"));
} catch (Exception ex) {
ex.printStackTrace();
}
There are two options:
1) use again get() method from the WebDriver to navigate to the new URL.
2) use navigate().to() method, but use fully qualified URL parameter. Eg. "https://www.google.com"
From the WebDriver javadoc: #param url The URL to load. It is best to use a fully qualified URL
The navigate() method is useful for using the context on the current web context. i.e. go back, forward.
Basically, the get() and navigate().to() do the same thing. I just tried both and they work.
Reference: http://www.seleniumeasy.com/selenium-tutorials/difference-between-webdriver-get-and-navigate

Upload Youtube using Proxy, per connection and not system wide

I have a Java code using youtube-api to upload videos. Until now I was using the system configuration to set the proxy (http and https) and everything is working fine that way. But now I have a new requirement regarding the way we use proxy on the server. As we have other services running on the very same server, they asked me to not configure the proxy using system wide approach, because this affect all the services using JVM.
System.setProperty("http.proxyHost", httpProxyHost);
System.setProperty("http.proxyPort", httpProxyPort);
and
System.setProperty("https.proxyHost", httpsProxyHost);
System.setProperty("https.proxyPort", httpsProxyPort);
I have spent the last couple days researching that on the Internet and didn't find anything useful. I found a explanation on the C# API what seems to be setting the proxy to the connection and I didn't find a way to implement this same approach on Java.
I want to do something like this:
service = new YouTubeService(APPLICATION_NAME, DEVELOPER_KEY);
service.setUserCredentials(userName, password);
uploader = new ResumableGDataFileUploader.Builder(
service, new URL(RESUMABLE_UPLOAD_URL), ms, newVideoEntry)
.title(videoTitle)
.trackProgress(listener, PROGRESS_UPDATE_INTERVAL)
.chunkSize(DEFAULT_CHUNK_SIZE).build();
// fictional code to show what I want to do
uploader.setProxyHttp(httpProxyHost, httpProxyPort);
uploader.setProxyHttps(httpsProxyHost, httpsProxyPort);
uploader.start();
This is very similar to what Java already allow us to do. See this http://docs.oracle.com/javase/6/docs/technotes/guides/net/proxies.html
I just resolved with the following code. Adapt the method setPersonalUrlConnectionFactory to set your proxy and call it passing as argument your uploader.
package com.google.gdata.client.uploader;
import com.google.gdata.client.media.ResumableGDataFileUploader;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.logging.Level;
import java.util.logging.Logger;
public class PersonalUrlConnectionInjector {
public static void setPersonalUrlConnectionFactory(ResumableGDataFileUploader uploader) {
try {
java.lang.reflect.Field field = uploader.getClass().getSuperclass().getDeclaredField("urlConnectionFactory");
field.setAccessible(true);
java.lang.reflect.Field modifiersField = java.lang.reflect.Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(field, field.getModifiers() & ~java.lang.reflect.Modifier.FINAL);
field.set(uploader, new UrlConnectionFactory() {
#Override
public HttpURLConnection create(URL url) throws IOException {
return new sun.net.www.protocol.http.HttpURLConnection(url, MY_PROXY);
}
});
} catch (Exception e) {
/* DO LOG */
}
}
}

Execute .NET application (no-install) from webpage (intranet) and pass argument(s)?

i built an intranet on .NET MVC. I'm also building a separate planning tool in Winforms (performance choice). I would now like to 'open' the planning tool from the intranet (IE7) and pass an argument (e.g. Workorder number) so I can display the planning for that specific item. Is this possible?
I have a .application file for the Winforms application. I'm also able to change everything on both the .NET MVC intranet and the Winforms planning tool.
You can't simply call the application from the HTML; that would be a security hole. However, you can have the application register to be able to handle these requests via the registry. You say "no-install", so this might be a problem. Maybe your app could modify the registry on the first load.
Anyway, the app would register to handle a specific protocol (like when you click on an itunes:// or ftp:// link).
Instead you'd have something like:
View workflow #3472
which then launches your app with the argument specified.
See http://msdn.microsoft.com/en-us/library/aa767914(VS.85).aspx . You say IE7, but this should work with other browsers, too, once the protocol is registered.
Yes you can do it.
private string _output = "";
public string Execute()
{
try
{
Process process = new Process();
process.OutputDataReceived += new DataReceivedEventHandler(process_OutputDataReceived);
process.StartInfo.FileName = "path to exe";
process.StartInfo.Arguments = "here you can pass arguments to exe";
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true;
Process currentProcess = Process.GetCurrentProcess();
process.StartInfo.UserName = currentProcess.StartInfo.UserName;
process.StartInfo.Password = currentProcess.StartInfo.Password;
process.Start();
process.BeginOutputReadLine();
process.WaitForExit();
return _output;
}
catch (Exception error)
{
return "ERROR : " + error.Message;
}
}
private void process_OutputDataReceived(object sender, DataReceivedEventArgs e)
{
if (e.Data != null)
{
_output += e.Data + Environment.NewLine;
}
}
It's a simple example. You can use different threads to read output and errors from exe.

Resources