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

Support moving static ode to another server #3134

Open
wants to merge 7 commits 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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions appinventor/appengine/build.xml
Original file line number Diff line number Diff line change
Expand Up @@ -634,6 +634,8 @@
<arg value="${build.extra.dir}"/>
<arg line="${client.flags} ${client.module}"/>
</java>
<copy todir="${build.war.dir}/ode"
file="${appinventor.dir}/appengine/extra/cdnok.js" />
</target>

<target name="devmode"
Expand Down
4 changes: 4 additions & 0 deletions appinventor/appengine/extra/cdnok.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
function cdnok() {
document.getElementById("odeblock").remove()
}
cdnok();
20 changes: 20 additions & 0 deletions appinventor/appengine/src/com/google/appinventor/client/Ode.java
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.rpc.ServiceDefTarget;
import com.google.gwt.user.client.rpc.StatusCodeException;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.CheckBox;
Expand Down Expand Up @@ -684,6 +685,14 @@ public void onUncaughtException(Throwable e) {
// This call also stores our sessionId in the backend. This will be checked
// when we go to save a file and if different file saving will be disabled
// Newer sessions invalidate older sessions.

setupOrigin(projectService);
setupOrigin(userInfoService);
setupOrigin(getMotdService);
setupOrigin(componentService);
setupOrigin(adminInfoService);
setupOrigin(tokenAuthService);

Promise.<Config>call(MESSAGES.serverUnavailable(),
c -> userInfoService.getSystemConfig(sessionId, c))
.then(result -> {
Expand Down Expand Up @@ -2344,6 +2353,17 @@ public boolean getDeleteAccountAllowed() {
return config.getDeleteAccountAllowed();
}

public static void setupOrigin(Object service) {
if (service instanceof ServiceDefTarget) {
String host = Window.Location.getProtocol() + "//" + Window.Location.getHost();
String oldUrl = ((ServiceDefTarget)service).getServiceEntryPoint();
if (oldUrl.startsWith(GWT.getModuleBaseURL())) {
String newUrl = host + "/" + GWT.getModuleName() + "/" + oldUrl.substring(GWT.getModuleBaseURL().length());
((ServiceDefTarget)service).setServiceEntryPoint(newUrl);
}
}
}

/**
* setRendezvousServer
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,28 @@

package com.google.appinventor.client.editor.simple.components;

import static com.google.appinventor.client.Ode.MESSAGES;

import com.google.appinventor.client.editor.youngandroid.DesignToolbar;
import com.google.appinventor.client.Ode;
import com.google.appinventor.client.editor.simple.SimpleEditor;

import com.google.appinventor.client.editor.youngandroid.DesignToolbar;

import com.google.appinventor.client.utils.MessageDialog;

import com.google.appinventor.client.widgets.properties.EditableProperty;

import com.google.appinventor.shared.rpc.components.FirebaseAuthService;
import com.google.appinventor.shared.rpc.components.FirebaseAuthServiceAsync;

import com.google.gwt.core.client.GWT;

import com.google.gwt.user.client.rpc.AsyncCallback;

import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.Widget;

import java.util.logging.Logger;

import static com.google.appinventor.client.Ode.MESSAGES;

/**
* Mock for the non-visible FirebaseDB component. This needs a separate mock
Expand Down Expand Up @@ -54,6 +60,7 @@ public class MockFirebaseDB extends MockNonVisibleComponent {
*/
public MockFirebaseDB(SimpleEditor editor, String type, Image iconImage) {
super(editor, type, iconImage);
Ode.setupOrigin(AUTH_SVC);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public ProjectListItem(Project project) {
initWidget(UI_BINDER.createAndBindUi(this));
this.getElement().setAttribute("data-exporturl",
"application/octet-stream:" + project.getProjectName() + ".aia:"
+ GWT.getModuleBaseURL() + ServerLayout.DOWNLOAD_SERVLET_BASE
+ ServerLayout.getModuleBaseURL() + ServerLayout.DOWNLOAD_SERVLET_BASE
+ ServerLayout.DOWNLOAD_PROJECT_SOURCE + "/" + project.getProjectId());
configureDraggable(this.getElement());
DateTimeFormat dateTimeFormat = DateTimeFormat.getFormat(DATE_TIME_MEDIUM);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,22 @@
// -*- mode: java; c-basic-offset: 2; -*-
// Copyright 2009-2011 Google, All Rights reserved
// Copyright 2011-2012 MIT, All rights reserved
// Copyright 2011-2024 MIT, All rights reserved
// Released under the Apache License, Version 2.0
// http://www.apache.org/licenses/LICENSE-2.0

package com.google.appinventor.client.utils;

import com.google.appinventor.client.ErrorReporter;

import com.google.appinventor.shared.rpc.ServerLayout;

import com.google.gwt.core.client.GWT;

import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.ui.Frame;
import com.google.gwt.user.client.ui.RootPanel;


/**
* Utility class to download files from the server.
*
Expand Down Expand Up @@ -45,7 +50,7 @@ private Downloader() {
*/
public final void download(String path) {
ErrorReporter.hide();
setUrl(GWT.getModuleBaseURL() + path);
setUrl(ServerLayout.getModuleBaseURL() + path);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ public void execute() {
return;
}

String url = GWT.getModuleBaseURL() +
String url = ServerLayout.getModuleBaseURL() +
ServerLayout.UPLOAD_SERVLET + "/" +
ServerLayout.UPLOAD_COMPONENT + "/" +
trimLeadingPath(fileUpload.getFilename());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,21 @@
package com.google.appinventor.client.wizards;

import com.google.appinventor.client.ErrorReporter;
import static com.google.appinventor.client.Ode.MESSAGES;
import com.google.appinventor.client.OdeAsyncCallback;
import com.google.appinventor.client.utils.Uploader;

import com.google.appinventor.shared.rpc.ServerLayout;
import com.google.appinventor.shared.rpc.UploadResponse;
import com.google.appinventor.shared.rpc.component.Component;

import com.google.gwt.core.client.GWT;

import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.FileUpload;
import com.google.gwt.user.client.ui.VerticalPanel;

import static com.google.appinventor.client.Ode.MESSAGES;

public class ComponentUploadWizard extends Wizard {
private static final String COMPONENT_ARCHIVE_EXTENSION = ".aix";
Expand Down Expand Up @@ -47,7 +49,7 @@ public void execute() {
return;
}

String url = GWT.getModuleBaseURL() +
String url = ServerLayout.getModuleBaseURL() +
ServerLayout.UPLOAD_SERVLET + "/" +
ServerLayout.UPLOAD_COMPONENT + "/" +
trimLeadingPath(uploadWiget.getFilename());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -165,9 +165,9 @@ public void onSuccess(Long date) {

// Use the folderNode's project id and file id in the upload URL so that the file is
// uploaded into that project and that folder in our back-end storage.
String uploadUrl = GWT.getModuleBaseURL() + ServerLayout.UPLOAD_SERVLET + "/" +
ServerLayout.UPLOAD_FILE + "/" + folderNode.getProjectId() + "/" +
folderNode.getFileId() + "/" + filename;
String uploadUrl = ServerLayout.getModuleBaseURL() + ServerLayout.UPLOAD_SERVLET + "/" +
ServerLayout.UPLOAD_FILE + "/" + folderNode.getProjectId() + "/" +
folderNode.getFileId() + "/" + filename;
Uploader.getInstance().upload(upload, uploadUrl,
new OdeAsyncCallback<UploadResponse>(MESSAGES.fileUploadError()) {
@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public KeystoreUploadWizard(final Command callbackAfterUpload) {
public void execute() {
String filename = upload.getFilename();
if (filename.endsWith(KEYSTORE_EXTENSION)) {
String uploadUrl = GWT.getModuleBaseURL() + ServerLayout.UPLOAD_SERVLET + "/" +
String uploadUrl = ServerLayout.getModuleBaseURL() + ServerLayout.UPLOAD_SERVLET + "/" +
ServerLayout.UPLOAD_USERFILE + "/" + StorageUtil.ANDROID_KEYSTORE_FILENAME;
Uploader.getInstance().upload(upload, uploadUrl,
new OdeAsyncCallback<UploadResponse>(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,15 +60,15 @@ public void execute() {
// Make sure the project name is legal and unique.
if (TextValidators.checkNewProjectName(filename, true)
!= TextValidators.ProjectNameStatus.SUCCESS) {

// Show Dialog Box and rename the project
new RequestNewProjectNameWizard(new RequestProjectNewNameInterface() {
@Override
public void getNewName(String name) {
upload(upload, name);
}
}, filename, true);

} else {
upload(upload, filename);
}
Expand All @@ -79,9 +79,9 @@ public void getNewName(String name) {
}
});
}

private void upload(FileUpload upload, String filename) {
String uploadUrl = GWT.getModuleBaseURL() + ServerLayout.UPLOAD_SERVLET + "/"
String uploadUrl = ServerLayout.getModuleBaseURL() + ServerLayout.UPLOAD_SERVLET + "/"
+ ServerLayout.UPLOAD_PROJECT + "/" + filename;
Uploader.getInstance().upload(upload, uploadUrl,
new OdeAsyncCallback<UploadResponse>(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,42 @@
* servlets.
*
*/
public abstract class OdeRemoteServiceServlet extends RemoteServiceServlet {

import com.google.gwt.user.server.rpc.SerializationPolicy;

import java.net.MalformedURLException;
import java.net.URL;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public abstract class OdeRemoteServiceServlet extends RemoteServiceServlet {
public final static String MODULE_ALIAS = "ode";
protected final UserInfoProvider userInfoProvider = LocalUser.getInstance();

@Override
protected SerializationPolicy doGetSerializationPolicy(final HttpServletRequest request,
final String moduleBaseURL, final String strongName) {

// true client side relative location is the app name
String newModuleBaseURL = moduleBaseURL;
try {
URL url = new URL(moduleBaseURL);

StringBuilder builder = new StringBuilder();
builder.append(url.getProtocol());
builder.append("://");
builder.append(url.getHost());
builder.append("/");
builder.append(MODULE_ALIAS);
builder.append("/");
newModuleBaseURL = builder.toString();

} catch (MalformedURLException ex) {
// we have no affect
}

return super.doGetSerializationPolicy(request, newModuleBaseURL, strongName);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@

package com.google.appinventor.shared.rpc;

import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.ServiceDefTarget;
jisqyv marked this conversation as resolved.
Show resolved Hide resolved

/**
* Configuration of the URL namespace on the ODE server.
*
Expand Down Expand Up @@ -206,4 +210,10 @@ public static String genRelativeDownloadPath(long projectId, String target) {
public static String genFullDownloadPath(long projectId, String target) {
return ODE_BASEURL + genRelativeDownloadPath(projectId, target);
}

public static String getModuleBaseURL() {
return Window.Location.getProtocol() + "//" + Window.Location.getHost() +
"/" + GWT.getModuleName() + "/";
}

}
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
// -*- mode: java; c-basic-offset: 2; -*-
// Copyright 2009-2011 Google, All Rights reserved
// Copyright 2011-2017 MIT, All rights reserved
// Copyright 2011-2024 MIT, All rights reserved
// Released under the Apache License, Version 2.0
// http://www.apache.org/licenses/LICENSE-2.0

package com.google.appinventor.shared.storage;

import com.google.appinventor.shared.rpc.ServerLayout;
import com.google.gwt.core.client.GWT;

/**
* Constants and utility methods related to storage.
Expand Down Expand Up @@ -251,7 +250,9 @@ public static boolean isFontFile(String filePath) {
* Returns the URL for the given project file.
*/
public static String getFileUrl(long projectId, String fileId) {
return GWT.getModuleBaseURL() + getFilePath(projectId, fileId);
// Note: Cannot call ode.GetModuleBaseURL() here because it is shared
// and Ode is not in scope on the server side.
jisqyv marked this conversation as resolved.
Show resolved Hide resolved
return (ServerLayout.getModuleBaseURL() + getFilePath(projectId, fileId));
}

/**
Expand Down
9 changes: 9 additions & 0 deletions appinventor/appengine/war/WEB-INF/appengine-web.xml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

<!-- These are not cached on purpose -->
<include path="/ode/**.nocache.*" expiration="0s" />
<include path="/ode/cdnok.js" expiration="3600s" />
<include path="/index.html" expiration="0s" />

<include path="/ode/**.cache.*" expiration="365d" />
Expand Down Expand Up @@ -178,5 +179,13 @@
<property name="http.keepAlive" value="true" />
<property name="http.maxConnections" value="5" />

<!-- Where to load ode from -->

<!-- Set this to the base URL of where ode is located. Leaving it blank -->
<!-- will load ode from the same host as the server. Note: base URL must be -->
<!-- a top level url. Aka https://example.com/ *not* -->
<!-- https://example.com/something. -->
<property name="ode.base" value="" />

</system-properties>
</appengine-web-app>
15 changes: 13 additions & 2 deletions appinventor/appengine/war/index.jsp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<%@page import="com.google.appinventor.server.Server,com.google.appinventor.common.version.AppInventorFeatures" %>
<%@page import="com.google.appinventor.server.flags.Flag" %>
<%
if (request.getScheme().equals("http") && Server.isProductionServer()
&& AppInventorFeatures.enableHttpRedirect()) {
Expand All @@ -16,9 +17,10 @@
if (AppInventorFeatures.enableHttpRedirect()) {
response.setHeader("Strict-Transport-Security", "max-age=3600");
}
final String odeBase = Flag.createFlag("ode.base", "").get();
%>
<!-- Copyright 2007-2009 Google Inc. All Rights Reserved. -->
<!-- Copyright 2011-2020 Massachusetts Institute of Technology. All Rights Reserved. -->
<!-- Copyright 2011-2024 Massachusetts Institute of Technology. All Rights Reserved. -->
<!DOCTYPE html>
<html>
<head>
Expand Down Expand Up @@ -62,8 +64,17 @@
<li> Firefox 52+ </li>
</ul>
</div>
<% if (!odeBase.isEmpty()) { %>
<div id=odeblock>
<h1>If you see this message for an extended period of time, it might be because
your internet service is blocking requests to <%= odeBase %>. Contact your
administrator to check on this and remove the block.
</h1>
</div>
<% } %>
<script type="text/javascript" src="static/closure-library/closure/goog/base.js"></script>
<script type="text/javascript" src="ode/ode.nocache.js"></script>
<script type="text/javascript" src="<%= odeBase %>ode/cdnok.js"></script>
<script type="text/javascript" src="<%= odeBase %>ode/ode.nocache.js"></script>
<script src="static/leaflet/leaflet.js"></script>
<script src="static/leaflet/leaflet.toolbar.js"></script>
<script src="static/leaflet/leaflet-vector-markers.min.js"></script>
Expand Down