Code refactor, adding GoLand workspace with Bazel plugin.
This commit is contained in:
		
							
								
								
									
										18
									
								
								.ijwb/.bazelproject
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								.ijwb/.bazelproject
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,18 @@
 | 
				
			|||||||
 | 
					directories:
 | 
				
			||||||
 | 
					  .
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Automatically includes all relevant targets under the 'directories' above
 | 
				
			||||||
 | 
					derive_targets_from_directories: true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					targets:
 | 
				
			||||||
 | 
					  # If source code isn't resolving, add additional targets that compile it here
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					additional_languages:
 | 
				
			||||||
 | 
					  # Uncomment any additional languages you want supported
 | 
				
			||||||
 | 
					  # dart
 | 
				
			||||||
 | 
					  # javascript
 | 
				
			||||||
 | 
					  # python
 | 
				
			||||||
 | 
					  # typescript
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					build_flags:
 | 
				
			||||||
 | 
					  --features=pure
 | 
				
			||||||
							
								
								
									
										11
									
								
								.ijwb/.blaze/modules/.project-data-dir.iml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								.ijwb/.blaze/modules/.project-data-dir.iml
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,11 @@
 | 
				
			|||||||
 | 
					<?xml version="1.0" encoding="UTF-8"?>
 | 
				
			||||||
 | 
					<module external.system.id="Blaze" type="WEB_MODULE" version="4">
 | 
				
			||||||
 | 
					  <component name="NewModuleRootManager">
 | 
				
			||||||
 | 
					    <content url="file://$MODULE_DIR$/../..">
 | 
				
			||||||
 | 
					      <excludeFolder url="file://$MODULE_DIR$/.." />
 | 
				
			||||||
 | 
					      <excludeFolder url="file://$MODULE_DIR$/../../.idea" />
 | 
				
			||||||
 | 
					    </content>
 | 
				
			||||||
 | 
					    <orderEntry type="inheritedJdk" />
 | 
				
			||||||
 | 
					    <orderEntry type="sourceFolder" forTests="false" />
 | 
				
			||||||
 | 
					  </component>
 | 
				
			||||||
 | 
					</module>
 | 
				
			||||||
							
								
								
									
										17
									
								
								.ijwb/.blaze/modules/.workspace.iml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								.ijwb/.blaze/modules/.workspace.iml
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,17 @@
 | 
				
			|||||||
 | 
					<?xml version="1.0" encoding="UTF-8"?>
 | 
				
			||||||
 | 
					<module external.system.id="Blaze" type="WEB_MODULE" version="4">
 | 
				
			||||||
 | 
					  <component name="Go" enabled="true" />
 | 
				
			||||||
 | 
					  <component name="NewModuleRootManager">
 | 
				
			||||||
 | 
					    <content url="file://$MODULE_DIR$/../../..">
 | 
				
			||||||
 | 
					      <sourceFolder url="file://$MODULE_DIR$/../../.." isTestSource="false" />
 | 
				
			||||||
 | 
					      <excludeFolder url="file://$MODULE_DIR$/../.." />
 | 
				
			||||||
 | 
					      <excludeFolder url="file://$MODULE_DIR$/../../../bazel-bin" />
 | 
				
			||||||
 | 
					      <excludeFolder url="file://$MODULE_DIR$/../../../bazel-genfiles" />
 | 
				
			||||||
 | 
					      <excludeFolder url="file://$MODULE_DIR$/../../../bazel-navigator" />
 | 
				
			||||||
 | 
					      <excludeFolder url="file://$MODULE_DIR$/../../../bazel-out" />
 | 
				
			||||||
 | 
					      <excludeFolder url="file://$MODULE_DIR$/../../../bazel-testlogs" />
 | 
				
			||||||
 | 
					    </content>
 | 
				
			||||||
 | 
					    <orderEntry type="inheritedJdk" />
 | 
				
			||||||
 | 
					    <orderEntry type="sourceFolder" forTests="false" />
 | 
				
			||||||
 | 
					  </component>
 | 
				
			||||||
 | 
					</module>
 | 
				
			||||||
							
								
								
									
										6
									
								
								.ijwb/.idea/$CACHE_FILE$
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								.ijwb/.idea/$CACHE_FILE$
									
									
									
										generated
									
									
									
										Normal file
									
								
							@ -0,0 +1,6 @@
 | 
				
			|||||||
 | 
					<?xml version="1.0" encoding="UTF-8"?>
 | 
				
			||||||
 | 
					<project version="4">
 | 
				
			||||||
 | 
					  <component name="NodePackageJsonFileManager">
 | 
				
			||||||
 | 
					    <packageJsonPaths />
 | 
				
			||||||
 | 
					  </component>
 | 
				
			||||||
 | 
					</project>
 | 
				
			||||||
							
								
								
									
										6
									
								
								.ijwb/.idea/.gitignore
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								.ijwb/.idea/.gitignore
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,6 @@
 | 
				
			|||||||
 | 
					# Default ignored files
 | 
				
			||||||
 | 
					/workspace.xml
 | 
				
			||||||
 | 
					# Project exclude paths
 | 
				
			||||||
 | 
					/.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										1
									
								
								.ijwb/.idea/.name
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								.ijwb/.idea/.name
									
									
									
										generated
									
									
									
										Normal file
									
								
							@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					navigator
 | 
				
			||||||
							
								
								
									
										3
									
								
								.ijwb/.idea/dictionaries/eve.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								.ijwb/.idea/dictionaries/eve.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							@ -0,0 +1,3 @@
 | 
				
			|||||||
 | 
					<component name="ProjectDictionaryState">
 | 
				
			||||||
 | 
					  <dictionary name="eve" />
 | 
				
			||||||
 | 
					</component>
 | 
				
			||||||
							
								
								
									
										6
									
								
								.ijwb/.idea/externalDependencies.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								.ijwb/.idea/externalDependencies.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							@ -0,0 +1,6 @@
 | 
				
			|||||||
 | 
					<?xml version="1.0" encoding="UTF-8"?>
 | 
				
			||||||
 | 
					<project version="4">
 | 
				
			||||||
 | 
					  <component name="ExternalDependencies">
 | 
				
			||||||
 | 
					    <plugin id="com.google.idea.bazel.ijwb" />
 | 
				
			||||||
 | 
					  </component>
 | 
				
			||||||
 | 
					</project>
 | 
				
			||||||
							
								
								
									
										72
									
								
								.ijwb/.idea/misc.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								.ijwb/.idea/misc.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							@ -0,0 +1,72 @@
 | 
				
			|||||||
 | 
					<?xml version="1.0" encoding="UTF-8"?>
 | 
				
			||||||
 | 
					<project version="4">
 | 
				
			||||||
 | 
					  <component name="MarkdownProjectSettings">
 | 
				
			||||||
 | 
					    <PreviewSettings splitEditorLayout="SPLIT" splitEditorPreview="PREVIEW" useGrayscaleRendering="false" zoomFactor="1.0" maxImageWidth="0" showGitHubPageIfSynced="false" allowBrowsingInPreview="false" synchronizePreviewPosition="true" highlightPreviewType="NONE" highlightFadeOut="5" highlightOnTyping="true" synchronizeSourcePosition="true" verticallyAlignSourceAndPreviewSyncPosition="true" showSearchHighlightsInPreview="false" showSelectionInPreview="true" openRemoteLinks="true">
 | 
				
			||||||
 | 
					      <PanelProvider>
 | 
				
			||||||
 | 
					        <provider providerId="com.vladsch.idea.multimarkdown.editor.swing.html.panel" providerName="Default - Swing" />
 | 
				
			||||||
 | 
					      </PanelProvider>
 | 
				
			||||||
 | 
					    </PreviewSettings>
 | 
				
			||||||
 | 
					    <ParserSettings gitHubSyntaxChange="false">
 | 
				
			||||||
 | 
					      <PegdownExtensions>
 | 
				
			||||||
 | 
					        <option name="ABBREVIATIONS" value="false" />
 | 
				
			||||||
 | 
					        <option name="ANCHORLINKS" value="true" />
 | 
				
			||||||
 | 
					        <option name="ASIDE" value="false" />
 | 
				
			||||||
 | 
					        <option name="ATXHEADERSPACE" value="true" />
 | 
				
			||||||
 | 
					        <option name="AUTOLINKS" value="true" />
 | 
				
			||||||
 | 
					        <option name="DEFINITIONS" value="false" />
 | 
				
			||||||
 | 
					        <option name="DEFINITION_BREAK_DOUBLE_BLANK_LINE" value="false" />
 | 
				
			||||||
 | 
					        <option name="FENCED_CODE_BLOCKS" value="true" />
 | 
				
			||||||
 | 
					        <option name="FOOTNOTES" value="false" />
 | 
				
			||||||
 | 
					        <option name="HARDWRAPS" value="false" />
 | 
				
			||||||
 | 
					        <option name="HTML_DEEP_PARSER" value="false" />
 | 
				
			||||||
 | 
					        <option name="INSERTED" value="false" />
 | 
				
			||||||
 | 
					        <option name="QUOTES" value="false" />
 | 
				
			||||||
 | 
					        <option name="RELAXEDHRULES" value="true" />
 | 
				
			||||||
 | 
					        <option name="SMARTS" value="false" />
 | 
				
			||||||
 | 
					        <option name="STRIKETHROUGH" value="true" />
 | 
				
			||||||
 | 
					        <option name="SUBSCRIPT" value="false" />
 | 
				
			||||||
 | 
					        <option name="SUPERSCRIPT" value="false" />
 | 
				
			||||||
 | 
					        <option name="SUPPRESS_HTML_BLOCKS" value="false" />
 | 
				
			||||||
 | 
					        <option name="SUPPRESS_INLINE_HTML" value="false" />
 | 
				
			||||||
 | 
					        <option name="TABLES" value="true" />
 | 
				
			||||||
 | 
					        <option name="TASKLISTITEMS" value="true" />
 | 
				
			||||||
 | 
					        <option name="TOC" value="false" />
 | 
				
			||||||
 | 
					        <option name="WIKILINKS" value="true" />
 | 
				
			||||||
 | 
					      </PegdownExtensions>
 | 
				
			||||||
 | 
					      <ParserOptions>
 | 
				
			||||||
 | 
					        <option name="COMMONMARK_LISTS" value="true" />
 | 
				
			||||||
 | 
					        <option name="DUMMY" value="false" />
 | 
				
			||||||
 | 
					        <option name="EMOJI_SHORTCUTS" value="true" />
 | 
				
			||||||
 | 
					        <option name="FLEXMARK_FRONT_MATTER" value="false" />
 | 
				
			||||||
 | 
					        <option name="GFM_LOOSE_BLANK_LINE_AFTER_ITEM_PARA" value="false" />
 | 
				
			||||||
 | 
					        <option name="GFM_TABLE_RENDERING" value="true" />
 | 
				
			||||||
 | 
					        <option name="GITBOOK_URL_ENCODING" value="false" />
 | 
				
			||||||
 | 
					        <option name="GITHUB_EMOJI_URL" value="false" />
 | 
				
			||||||
 | 
					        <option name="GITHUB_LISTS" value="false" />
 | 
				
			||||||
 | 
					        <option name="GITHUB_WIKI_LINKS" value="true" />
 | 
				
			||||||
 | 
					        <option name="JEKYLL_FRONT_MATTER" value="false" />
 | 
				
			||||||
 | 
					        <option name="SIM_TOC_BLANK_LINE_SPACER" value="true" />
 | 
				
			||||||
 | 
					      </ParserOptions>
 | 
				
			||||||
 | 
					    </ParserSettings>
 | 
				
			||||||
 | 
					    <HtmlSettings headerTopEnabled="false" headerBottomEnabled="false" bodyTopEnabled="false" bodyBottomEnabled="false" embedUrlContent="false" addPageHeader="true" embedImages="false" embedHttpImages="false">
 | 
				
			||||||
 | 
					      <GeneratorProvider>
 | 
				
			||||||
 | 
					        <provider providerId="com.vladsch.idea.multimarkdown.editor.swing.html.generator" providerName="Default Swing HTML Generator" />
 | 
				
			||||||
 | 
					      </GeneratorProvider>
 | 
				
			||||||
 | 
					      <headerTop />
 | 
				
			||||||
 | 
					      <headerBottom />
 | 
				
			||||||
 | 
					      <bodyTop />
 | 
				
			||||||
 | 
					      <bodyBottom />
 | 
				
			||||||
 | 
					    </HtmlSettings>
 | 
				
			||||||
 | 
					    <CssSettings previewScheme="UI_SCHEME" cssUri="" isCssUriEnabled="false" isCssTextEnabled="false" isDynamicPageWidth="true">
 | 
				
			||||||
 | 
					      <StylesheetProvider>
 | 
				
			||||||
 | 
					        <provider providerId="com.vladsch.idea.multimarkdown.editor.swing.html.css" providerName="Default Swing Stylesheet" />
 | 
				
			||||||
 | 
					      </StylesheetProvider>
 | 
				
			||||||
 | 
					      <ScriptProviders />
 | 
				
			||||||
 | 
					      <cssText />
 | 
				
			||||||
 | 
					    </CssSettings>
 | 
				
			||||||
 | 
					    <HtmlExportSettings updateOnSave="false" parentDir="$ProjectFileDir$" targetDir="$ProjectFileDir$" cssDir="" scriptDir="" plainHtml="false" imageDir="" copyLinkedImages="false" imageUniquifyType="0" targetExt="" useTargetExt="false" noCssNoScripts="false" linkToExportedHtml="true" exportOnSettingsChange="true" regenerateOnProjectOpen="false" linkFormatType="HTTP_ABSOLUTE" />
 | 
				
			||||||
 | 
					    <LinkMapSettings>
 | 
				
			||||||
 | 
					      <textMaps />
 | 
				
			||||||
 | 
					    </LinkMapSettings>
 | 
				
			||||||
 | 
					  </component>
 | 
				
			||||||
 | 
					</project>
 | 
				
			||||||
							
								
								
									
										9
									
								
								.ijwb/.idea/modules.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								.ijwb/.idea/modules.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							@ -0,0 +1,9 @@
 | 
				
			|||||||
 | 
					<?xml version="1.0" encoding="UTF-8"?>
 | 
				
			||||||
 | 
					<project version="4">
 | 
				
			||||||
 | 
					  <component name="ProjectModuleManager">
 | 
				
			||||||
 | 
					    <modules>
 | 
				
			||||||
 | 
					      <module fileurl="file://$PROJECT_DIR$/.blaze/modules/.project-data-dir.iml" filepath="$PROJECT_DIR$/.blaze/modules/.project-data-dir.iml" />
 | 
				
			||||||
 | 
					      <module fileurl="file://$PROJECT_DIR$/.blaze/modules/.workspace.iml" filepath="$PROJECT_DIR$/.blaze/modules/.workspace.iml" />
 | 
				
			||||||
 | 
					    </modules>
 | 
				
			||||||
 | 
					  </component>
 | 
				
			||||||
 | 
					</project>
 | 
				
			||||||
							
								
								
									
										18
									
								
								.ijwb/.idea/runConfigurations.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								.ijwb/.idea/runConfigurations.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							@ -0,0 +1,18 @@
 | 
				
			|||||||
 | 
					<?xml version="1.0" encoding="UTF-8"?>
 | 
				
			||||||
 | 
					<project version="4">
 | 
				
			||||||
 | 
					  <component name="RunConfigurationProducerService">
 | 
				
			||||||
 | 
					    <option name="ignoredProducers">
 | 
				
			||||||
 | 
					      <set>
 | 
				
			||||||
 | 
					        <option value="com.goide.execution.application.GoApplicationRunConfigurationProducer" />
 | 
				
			||||||
 | 
					        <option value="com.goide.execution.testing.frameworks.gobench.GobenchRunConfigurationProducer" />
 | 
				
			||||||
 | 
					        <option value="com.goide.execution.testing.frameworks.gocheck.GocheckRunConfigurationProducer" />
 | 
				
			||||||
 | 
					        <option value="com.goide.execution.testing.frameworks.gotest.GotestRunConfigurationProducer" />
 | 
				
			||||||
 | 
					        <option value="com.intellij.javascript.jest.JestRunConfigurationProducer" />
 | 
				
			||||||
 | 
					        <option value="com.intellij.javascript.protractor.ProtractorRunConfigurationProducer" />
 | 
				
			||||||
 | 
					        <option value="com.intellij.lang.javascript.buildTools.grunt.rc.GruntRunConfigurationProducer" />
 | 
				
			||||||
 | 
					        <option value="com.intellij.lang.javascript.buildTools.gulp.rc.GulpRunConfigurationProducer" />
 | 
				
			||||||
 | 
					        <option value="com.intellij.lang.javascript.buildTools.npm.rc.NpmRunConfigurationProducer" />
 | 
				
			||||||
 | 
					      </set>
 | 
				
			||||||
 | 
					    </option>
 | 
				
			||||||
 | 
					  </component>
 | 
				
			||||||
 | 
					</project>
 | 
				
			||||||
							
								
								
									
										6
									
								
								.ijwb/.idea/vcs.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								.ijwb/.idea/vcs.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							@ -0,0 +1,6 @@
 | 
				
			|||||||
 | 
					<?xml version="1.0" encoding="UTF-8"?>
 | 
				
			||||||
 | 
					<project version="4">
 | 
				
			||||||
 | 
					  <component name="VcsDirectoryMappings">
 | 
				
			||||||
 | 
					    <mapping directory="$PROJECT_DIR$/.." vcs="Git" />
 | 
				
			||||||
 | 
					  </component>
 | 
				
			||||||
 | 
					</project>
 | 
				
			||||||
							
								
								
									
										49
									
								
								.ijwb/.idea/watcherTasks.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								.ijwb/.idea/watcherTasks.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							@ -0,0 +1,49 @@
 | 
				
			|||||||
 | 
					<?xml version="1.0" encoding="UTF-8"?>
 | 
				
			||||||
 | 
					<project version="4">
 | 
				
			||||||
 | 
					  <component name="ProjectTasksOptions">
 | 
				
			||||||
 | 
					    <TaskOptions isEnabled="true">
 | 
				
			||||||
 | 
					      <option name="arguments" value="fmt $FilePath$" />
 | 
				
			||||||
 | 
					      <option name="checkSyntaxErrors" value="true" />
 | 
				
			||||||
 | 
					      <option name="description" />
 | 
				
			||||||
 | 
					      <option name="exitCodeBehavior" value="ERROR" />
 | 
				
			||||||
 | 
					      <option name="fileExtension" value="go" />
 | 
				
			||||||
 | 
					      <option name="immediateSync" value="true" />
 | 
				
			||||||
 | 
					      <option name="name" value="go fmt" />
 | 
				
			||||||
 | 
					      <option name="output" value="$FilePath$" />
 | 
				
			||||||
 | 
					      <option name="outputFilters">
 | 
				
			||||||
 | 
					        <array />
 | 
				
			||||||
 | 
					      </option>
 | 
				
			||||||
 | 
					      <option name="outputFromStdout" value="false" />
 | 
				
			||||||
 | 
					      <option name="program" value="$GoExecPath$" />
 | 
				
			||||||
 | 
					      <option name="runOnExternalChanges" value="false" />
 | 
				
			||||||
 | 
					      <option name="scopeName" value="Project Files" />
 | 
				
			||||||
 | 
					      <option name="trackOnlyRoot" value="true" />
 | 
				
			||||||
 | 
					      <option name="workingDir" value="$ProjectFileDir$" />
 | 
				
			||||||
 | 
					      <envs>
 | 
				
			||||||
 | 
					        <env name="GOROOT" value="$GOROOT$" />
 | 
				
			||||||
 | 
					        <env name="GOPATH" value="$GOPATH$" />
 | 
				
			||||||
 | 
					        <env name="PATH" value="$GoBinDirs$" />
 | 
				
			||||||
 | 
					      </envs>
 | 
				
			||||||
 | 
					    </TaskOptions>
 | 
				
			||||||
 | 
					    <TaskOptions isEnabled="true">
 | 
				
			||||||
 | 
					      <option name="arguments" value="run //:gazelle -- -go_prefix git.eve.moe/jackyyf/navigator" />
 | 
				
			||||||
 | 
					      <option name="checkSyntaxErrors" value="true" />
 | 
				
			||||||
 | 
					      <option name="description" />
 | 
				
			||||||
 | 
					      <option name="exitCodeBehavior" value="ERROR" />
 | 
				
			||||||
 | 
					      <option name="fileExtension" value="go" />
 | 
				
			||||||
 | 
					      <option name="immediateSync" value="true" />
 | 
				
			||||||
 | 
					      <option name="name" value="gazelle" />
 | 
				
			||||||
 | 
					      <option name="output" value="" />
 | 
				
			||||||
 | 
					      <option name="outputFilters">
 | 
				
			||||||
 | 
					        <array />
 | 
				
			||||||
 | 
					      </option>
 | 
				
			||||||
 | 
					      <option name="outputFromStdout" value="false" />
 | 
				
			||||||
 | 
					      <option name="program" value="bazel" />
 | 
				
			||||||
 | 
					      <option name="runOnExternalChanges" value="true" />
 | 
				
			||||||
 | 
					      <option name="scopeName" value="All Places" />
 | 
				
			||||||
 | 
					      <option name="trackOnlyRoot" value="false" />
 | 
				
			||||||
 | 
					      <option name="workingDir" value="$Projectpath$" />
 | 
				
			||||||
 | 
					      <envs />
 | 
				
			||||||
 | 
					    </TaskOptions>
 | 
				
			||||||
 | 
					  </component>
 | 
				
			||||||
 | 
					</project>
 | 
				
			||||||
@ -10,15 +10,16 @@ go_library(
 | 
				
			|||||||
    importpath = "git.eve.moe/jackyyf/navigator",
 | 
					    importpath = "git.eve.moe/jackyyf/navigator",
 | 
				
			||||||
    visibility = ["//visibility:private"],
 | 
					    visibility = ["//visibility:private"],
 | 
				
			||||||
    deps = [
 | 
					    deps = [
 | 
				
			||||||
 | 
					        "//api/beacon/v1:go_default_library",
 | 
				
			||||||
 | 
					        "//api/navigator:go_default_library",
 | 
				
			||||||
        "//ipgeo:go_default_library",
 | 
					        "//ipgeo:go_default_library",
 | 
				
			||||||
        "//mapping:go_default_library",
 | 
					        "//mapping:go_default_library",
 | 
				
			||||||
        "@com_github_ipipdotnet_ipdb_go//:go_default_library",
 | 
					 | 
				
			||||||
    ],
 | 
					    ],
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
go_binary(
 | 
					go_binary(
 | 
				
			||||||
    name = "navigator",
 | 
					    name = "navigator",
 | 
				
			||||||
	pure = "on",
 | 
					    data = glob(["rules/**"]),
 | 
				
			||||||
    embed = [":go_default_library"],
 | 
					    embed = [":go_default_library"],
 | 
				
			||||||
    visibility = ["//visibility:public"],
 | 
					    visibility = ["//visibility:public"],
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										8
									
								
								api/beacon/BUILD.bazel
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								api/beacon/BUILD.bazel
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,8 @@
 | 
				
			|||||||
 | 
					load("@io_bazel_rules_go//go:def.bzl", "go_library")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					go_library(
 | 
				
			||||||
 | 
					    name = "go_default_library",
 | 
				
			||||||
 | 
					    srcs = ["api.go"],
 | 
				
			||||||
 | 
					    importpath = "git.eve.moe/jackyyf/navigator/api/beacon",
 | 
				
			||||||
 | 
					    visibility = ["//visibility:public"],
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
							
								
								
									
										18
									
								
								api/beacon/api.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								api/beacon/api.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,18 @@
 | 
				
			|||||||
 | 
					package beacon
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"net/http"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var (
 | 
				
			||||||
 | 
						apiServeMux = http.NewServeMux()
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func init() {
 | 
				
			||||||
 | 
						http.Handle("/beacon/", http.StripPrefix("/beacon", apiServeMux))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func RegisterApi(version string, handler http.Handler) {
 | 
				
			||||||
 | 
						apiServeMux.Handle(fmt.Sprintf("/%s/", version), http.StripPrefix(fmt.Sprint("/", version), handler))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										13
									
								
								api/beacon/v1/BUILD.bazel
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								api/beacon/v1/BUILD.bazel
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,13 @@
 | 
				
			|||||||
 | 
					load("@io_bazel_rules_go//go:def.bzl", "go_library")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					go_library(
 | 
				
			||||||
 | 
					    name = "go_default_library",
 | 
				
			||||||
 | 
					    srcs = ["api.go"],
 | 
				
			||||||
 | 
					    importpath = "git.eve.moe/jackyyf/navigator/api/beacon/v1",
 | 
				
			||||||
 | 
					    visibility = ["//visibility:public"],
 | 
				
			||||||
 | 
					    deps = [
 | 
				
			||||||
 | 
					        "//api/beacon:go_default_library",
 | 
				
			||||||
 | 
					        "//mapping:go_default_library",
 | 
				
			||||||
 | 
					        "//utils:go_default_library",
 | 
				
			||||||
 | 
					    ],
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
							
								
								
									
										33
									
								
								api/beacon/v1/api.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								api/beacon/v1/api.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,33 @@
 | 
				
			|||||||
 | 
					package v1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"encoding/json"
 | 
				
			||||||
 | 
						"git.eve.moe/jackyyf/navigator/api/beacon"
 | 
				
			||||||
 | 
						"git.eve.moe/jackyyf/navigator/mapping"
 | 
				
			||||||
 | 
						"git.eve.moe/jackyyf/navigator/utils"
 | 
				
			||||||
 | 
						"net/http"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var (
 | 
				
			||||||
 | 
						serveMux = http.NewServeMux()
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func init() {
 | 
				
			||||||
 | 
						serveMux.HandleFunc("/getNodes", func(resp http.ResponseWriter, req *http.Request) {
 | 
				
			||||||
 | 
							host := utils.GetRemoteIP(req)
 | 
				
			||||||
 | 
							nodes := mapping.GetNodes()
 | 
				
			||||||
 | 
							if nodes == nil {
 | 
				
			||||||
 | 
								utils.ResponseWithJsonError(resp, http.StatusInternalServerError, "Unable to get nodes")
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							suffix := mapping.GetSuffix(host)
 | 
				
			||||||
 | 
							resp.Header().Set("Content-Type", "application/json")
 | 
				
			||||||
 | 
							resp.WriteHeader(http.StatusOK)
 | 
				
			||||||
 | 
							jsonEncoder := json.NewEncoder(resp)
 | 
				
			||||||
 | 
							jsonEncoder.Encode(map[string]interface{}{
 | 
				
			||||||
 | 
								"nodes":  nodes,
 | 
				
			||||||
 | 
								"suffix": suffix,
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						beacon.RegisterApi("v1", serveMux)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										13
									
								
								api/navigator/BUILD.bazel
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								api/navigator/BUILD.bazel
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,13 @@
 | 
				
			|||||||
 | 
					load("@io_bazel_rules_go//go:def.bzl", "go_library")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					go_library(
 | 
				
			||||||
 | 
					    name = "go_default_library",
 | 
				
			||||||
 | 
					    srcs = ["api.go"],
 | 
				
			||||||
 | 
					    importpath = "git.eve.moe/jackyyf/navigator/api/navigator",
 | 
				
			||||||
 | 
					    visibility = ["//visibility:public"],
 | 
				
			||||||
 | 
					    deps = [
 | 
				
			||||||
 | 
					        "//ipgeo:go_default_library",
 | 
				
			||||||
 | 
					        "//mapping:go_default_library",
 | 
				
			||||||
 | 
					        "//utils:go_default_library",
 | 
				
			||||||
 | 
					    ],
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
							
								
								
									
										109
									
								
								api/navigator/api.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										109
									
								
								api/navigator/api.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,109 @@
 | 
				
			|||||||
 | 
					package navigator
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"encoding/json"
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"git.eve.moe/jackyyf/navigator/ipgeo"
 | 
				
			||||||
 | 
						"git.eve.moe/jackyyf/navigator/mapping"
 | 
				
			||||||
 | 
						"git.eve.moe/jackyyf/navigator/utils"
 | 
				
			||||||
 | 
						"log"
 | 
				
			||||||
 | 
						"net"
 | 
				
			||||||
 | 
						"net/http"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						errIPv4Only = "Navigator works for valid IPv4 only :)"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func init() {
 | 
				
			||||||
 | 
						http.HandleFunc("/healthz", func(resp http.ResponseWriter, req *http.Request) {
 | 
				
			||||||
 | 
							resp.WriteHeader(200)
 | 
				
			||||||
 | 
							resp.Write([]byte("ok"))
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						http.HandleFunc("/info", func(resp http.ResponseWriter, req *http.Request) {
 | 
				
			||||||
 | 
							var host string
 | 
				
			||||||
 | 
							if argIp := req.FormValue("ip"); argIp != "" {
 | 
				
			||||||
 | 
								host = argIp
 | 
				
			||||||
 | 
								if net.ParseIP(host).To4() == nil {
 | 
				
			||||||
 | 
									utils.ResponseWithError(resp, http.StatusPreconditionFailed, errIPv4Only)
 | 
				
			||||||
 | 
									return
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								host = utils.GetRemoteIP(req)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							db := ipgeo.Get()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							info_cn, err := db.FindInfo(host, "CN")
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								fmt.Fprintf(resp, "IP %s not found in the database.", host)
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							info_en, err := db.FindInfo(host, "EN")
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								fmt.Fprintf(resp, "IP %s not found in the database.", host)
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							resp.Header().Set("Content-Type", "text/plain")
 | 
				
			||||||
 | 
							resp.WriteHeader(http.StatusOK)
 | 
				
			||||||
 | 
							server := mapping.Get(host)
 | 
				
			||||||
 | 
							fmt.Fprintln(resp, "您的IP:", host)
 | 
				
			||||||
 | 
							fmt.Fprintln(resp, "数据库中IP所属位置:", utils.BuildLocation(info_cn))
 | 
				
			||||||
 | 
							if info_cn.IspDomain != "" {
 | 
				
			||||||
 | 
								fmt.Fprintln(resp, "数据库中IP所属运营商:", info_cn.IspDomain)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							fmt.Fprintln(resp, "您被分配的CDN节点为:", server)
 | 
				
			||||||
 | 
							fmt.Fprintln(resp)
 | 
				
			||||||
 | 
							fmt.Fprintln(resp, strings.Repeat("=", 72))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							fmt.Fprintln(resp, "Your IP:", host)
 | 
				
			||||||
 | 
							fmt.Fprintln(resp, "Location for your IP according our database:", utils.BuildLocation(info_en))
 | 
				
			||||||
 | 
							if info_en.IspDomain != "" {
 | 
				
			||||||
 | 
								fmt.Fprintln(resp, "ISP for your IP according our database:", info_en.IspDomain)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							fmt.Fprintln(resp, "Allocated CDN node for you:", server)
 | 
				
			||||||
 | 
							fmt.Fprintln(resp)
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						http.HandleFunc("/mapping", func(resp http.ResponseWriter, req *http.Request) {
 | 
				
			||||||
 | 
							host := utils.GetRemoteIP(req)
 | 
				
			||||||
 | 
							resp.Header().Set("Content-Type", "text/plain")
 | 
				
			||||||
 | 
							resp.WriteHeader(http.StatusOK)
 | 
				
			||||||
 | 
							server := mapping.Get(host)
 | 
				
			||||||
 | 
							fmt.Fprint(resp, server)
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						http.HandleFunc("/getMapping", func(resp http.ResponseWriter, req *http.Request) {
 | 
				
			||||||
 | 
							ip := req.FormValue("ip")
 | 
				
			||||||
 | 
							if net.ParseIP(ip).To4() == nil {
 | 
				
			||||||
 | 
								utils.ResponseWithError(resp, http.StatusBadRequest, errIPv4Only)
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							resp.Header().Set("Content-Type", "text/plain")
 | 
				
			||||||
 | 
							resp.WriteHeader(http.StatusOK)
 | 
				
			||||||
 | 
							server := mapping.Get(ip)
 | 
				
			||||||
 | 
							log.Printf("%s => %s\n", ip, server)
 | 
				
			||||||
 | 
							fmt.Fprint(resp, server)
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						http.HandleFunc("/getNodes", func(resp http.ResponseWriter, req *http.Request) {
 | 
				
			||||||
 | 
							ip := req.FormValue("ip")
 | 
				
			||||||
 | 
							if net.ParseIP(ip).To4() == nil {
 | 
				
			||||||
 | 
								utils.ResponseWithError(resp, http.StatusBadRequest, errIPv4Only)
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							nodes := mapping.GetNodes()
 | 
				
			||||||
 | 
							if nodes == nil {
 | 
				
			||||||
 | 
								utils.ResponseWithJsonError(resp, http.StatusInternalServerError, "Unable to get nodes")
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							suffix := mapping.GetSuffix(ip)
 | 
				
			||||||
 | 
							resp.Header().Set("Content-Type", "application/json")
 | 
				
			||||||
 | 
							resp.WriteHeader(http.StatusOK)
 | 
				
			||||||
 | 
							jsonEncoder := json.NewEncoder(resp)
 | 
				
			||||||
 | 
							ret := make([]string, 0, len(nodes))
 | 
				
			||||||
 | 
							for _, node := range nodes {
 | 
				
			||||||
 | 
								ret = append(ret, node+suffix)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							jsonEncoder.Encode(ret)
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										183
									
								
								main.go
									
									
									
									
									
								
							
							
						
						
									
										183
									
								
								main.go
									
									
									
									
									
								
							@ -1,197 +1,24 @@
 | 
				
			|||||||
package main
 | 
					package main
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"encoding/json"
 | 
					 | 
				
			||||||
	"flag"
 | 
						"flag"
 | 
				
			||||||
	"fmt"
 | 
						_ "git.eve.moe/jackyyf/navigator/api/beacon/v1"
 | 
				
			||||||
	"log"
 | 
						_ "git.eve.moe/jackyyf/navigator/api/navigator"
 | 
				
			||||||
	"net"
 | 
					 | 
				
			||||||
	"net/http"
 | 
					 | 
				
			||||||
	_ "net/http/pprof"
 | 
					 | 
				
			||||||
	"strings"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	"git.eve.moe/jackyyf/navigator/ipgeo"
 | 
						"git.eve.moe/jackyyf/navigator/ipgeo"
 | 
				
			||||||
	"git.eve.moe/jackyyf/navigator/mapping"
 | 
						"git.eve.moe/jackyyf/navigator/mapping"
 | 
				
			||||||
	"github.com/ipipdotnet/ipdb-go"
 | 
						"log"
 | 
				
			||||||
 | 
						"net/http"
 | 
				
			||||||
 | 
						_ "net/http/pprof"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const (
 | 
					 | 
				
			||||||
	errIPv4Only      = "Navigator works for valid IPv4 only :)"
 | 
					 | 
				
			||||||
	remoteAddrHeader = "X-NAV-REMOTE-IP"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type errorMessage struct {
 | 
					 | 
				
			||||||
	Error string `json:error`
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var (
 | 
					var (
 | 
				
			||||||
	listen_spec = flag.String("bind", "127.0.0.1:8086", "http server bind spec")
 | 
						listen_spec = flag.String("bind", "127.0.0.1:8086", "http server bind spec")
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func responseWithError(resp http.ResponseWriter, statusCode int, message string) {
 | 
					 | 
				
			||||||
	resp.Header().Set("Content-Type", "text/plain")
 | 
					 | 
				
			||||||
	resp.WriteHeader(statusCode)
 | 
					 | 
				
			||||||
	resp.Write([]byte("error: " + message))
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func responseWithJsonError(resp http.ResponseWriter, statusCode int, message string) {
 | 
					 | 
				
			||||||
	resp.Header().Set("Content-Type", "application/json")
 | 
					 | 
				
			||||||
	resp.WriteHeader(statusCode)
 | 
					 | 
				
			||||||
	encoder := json.NewEncoder(resp)
 | 
					 | 
				
			||||||
	err := encoder.Encode(&errorMessage{
 | 
					 | 
				
			||||||
		Error: message,
 | 
					 | 
				
			||||||
	})
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		// This should never happen
 | 
					 | 
				
			||||||
		panic("json marshal failed, check code")
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func getRemoteIP(req *http.Request) string {
 | 
					 | 
				
			||||||
	if addr := req.Header.Get(remoteAddrHeader); addr != "" {
 | 
					 | 
				
			||||||
		if net.ParseIP(addr).To4() == nil {
 | 
					 | 
				
			||||||
			return ""
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		return addr
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	host, _, err := net.SplitHostPort(req.RemoteAddr)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return ""
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if net.ParseIP(host).To4() == nil {
 | 
					 | 
				
			||||||
		return ""
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return host
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func buildLocation(info *ipdb.CityInfo) string {
 | 
					 | 
				
			||||||
	ret := ""
 | 
					 | 
				
			||||||
	if info.CountryName != "" {
 | 
					 | 
				
			||||||
		ret += info.CountryName + " "
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if info.RegionName != "" {
 | 
					 | 
				
			||||||
		ret += info.RegionName + " "
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if info.CityName != "" {
 | 
					 | 
				
			||||||
		ret += info.CityName + " "
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return strings.TrimSpace(ret)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func main() {
 | 
					func main() {
 | 
				
			||||||
	flag.Parse()
 | 
						flag.Parse()
 | 
				
			||||||
	ipgeo.Initialize()
 | 
						ipgeo.Initialize()
 | 
				
			||||||
	mapping.Initialize()
 | 
						mapping.Initialize()
 | 
				
			||||||
 | 
					 | 
				
			||||||
	http.HandleFunc("/healthz", func(resp http.ResponseWriter, req *http.Request) {
 | 
					 | 
				
			||||||
		resp.WriteHeader(200)
 | 
					 | 
				
			||||||
		resp.Write([]byte("ok"))
 | 
					 | 
				
			||||||
	})
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	http.HandleFunc("/info", func(resp http.ResponseWriter, req *http.Request) {
 | 
					 | 
				
			||||||
		var host string
 | 
					 | 
				
			||||||
		if argIp := req.FormValue("ip"); argIp != "" {
 | 
					 | 
				
			||||||
			host = argIp
 | 
					 | 
				
			||||||
			if net.ParseIP(host).To4() == nil {
 | 
					 | 
				
			||||||
				responseWithError(resp, http.StatusPreconditionFailed, errIPv4Only)
 | 
					 | 
				
			||||||
				return
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			host = getRemoteIP(req)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		db := ipgeo.Get()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		info_cn, err := db.FindInfo(host, "CN")
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			fmt.Fprintf(resp, "IP %s not found in the database.", host)
 | 
					 | 
				
			||||||
			return
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		info_en, err := db.FindInfo(host, "EN")
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			fmt.Fprintf(resp, "IP %s not found in the database.", host)
 | 
					 | 
				
			||||||
			return
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		resp.Header().Set("Content-Type", "text/plain")
 | 
					 | 
				
			||||||
		resp.WriteHeader(http.StatusOK)
 | 
					 | 
				
			||||||
		server := mapping.Get(host)
 | 
					 | 
				
			||||||
		fmt.Fprintln(resp, "您的IP:", host)
 | 
					 | 
				
			||||||
		fmt.Fprintln(resp, "数据库中IP所属位置:", buildLocation(info_cn))
 | 
					 | 
				
			||||||
		if info_cn.IspDomain != "" {
 | 
					 | 
				
			||||||
			fmt.Fprintln(resp, "数据库中IP所属运营商:", info_cn.IspDomain)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		fmt.Fprintln(resp, "您被分配的CDN节点为:", server)
 | 
					 | 
				
			||||||
		fmt.Fprintln(resp)
 | 
					 | 
				
			||||||
		fmt.Fprintln(resp, strings.Repeat("=", 72))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		fmt.Fprintln(resp, "Your IP:", host)
 | 
					 | 
				
			||||||
		fmt.Fprintln(resp, "Location for your IP according our database:", buildLocation(info_en))
 | 
					 | 
				
			||||||
		if info_en.IspDomain != "" {
 | 
					 | 
				
			||||||
			fmt.Fprintln(resp, "ISP for your IP according our database:", info_en.IspDomain)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		fmt.Fprintln(resp, "Allocated CDN node for you:", server)
 | 
					 | 
				
			||||||
		fmt.Fprintln(resp)
 | 
					 | 
				
			||||||
	})
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	http.HandleFunc("/mapping", func(resp http.ResponseWriter, req *http.Request) {
 | 
					 | 
				
			||||||
		host := getRemoteIP(req)
 | 
					 | 
				
			||||||
		resp.Header().Set("Content-Type", "text/plain")
 | 
					 | 
				
			||||||
		resp.WriteHeader(http.StatusOK)
 | 
					 | 
				
			||||||
		server := mapping.Get(host)
 | 
					 | 
				
			||||||
		fmt.Fprint(resp, server)
 | 
					 | 
				
			||||||
	})
 | 
					 | 
				
			||||||
	http.HandleFunc("/getMapping", func(resp http.ResponseWriter, req *http.Request) {
 | 
					 | 
				
			||||||
		ip := req.FormValue("ip")
 | 
					 | 
				
			||||||
		if net.ParseIP(ip).To4() == nil {
 | 
					 | 
				
			||||||
			responseWithError(resp, http.StatusBadRequest, errIPv4Only)
 | 
					 | 
				
			||||||
			return
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		resp.Header().Set("Content-Type", "text/plain")
 | 
					 | 
				
			||||||
		resp.WriteHeader(http.StatusOK)
 | 
					 | 
				
			||||||
		server := mapping.Get(ip)
 | 
					 | 
				
			||||||
		log.Printf("%s => %s\n", ip, server)
 | 
					 | 
				
			||||||
		fmt.Fprint(resp, server)
 | 
					 | 
				
			||||||
	})
 | 
					 | 
				
			||||||
	http.HandleFunc("/getNodes", func(resp http.ResponseWriter, req *http.Request) {
 | 
					 | 
				
			||||||
		ip := req.FormValue("ip")
 | 
					 | 
				
			||||||
		if net.ParseIP(ip).To4() == nil {
 | 
					 | 
				
			||||||
			responseWithError(resp, http.StatusBadRequest, errIPv4Only)
 | 
					 | 
				
			||||||
			return
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		nodes := mapping.GetNodes()
 | 
					 | 
				
			||||||
		if nodes == nil {
 | 
					 | 
				
			||||||
			responseWithJsonError(resp, http.StatusInternalServerError, "Unable to get nodes")
 | 
					 | 
				
			||||||
			return
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		suffix := mapping.GetSuffix(ip)
 | 
					 | 
				
			||||||
		resp.Header().Set("Content-Type", "application/json")
 | 
					 | 
				
			||||||
		resp.WriteHeader(http.StatusOK)
 | 
					 | 
				
			||||||
		jsonEncoder := json.NewEncoder(resp)
 | 
					 | 
				
			||||||
		ret := make([]string, 0, len(nodes))
 | 
					 | 
				
			||||||
		for _, node := range nodes {
 | 
					 | 
				
			||||||
			ret = append(ret, node+suffix)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		jsonEncoder.Encode(ret)
 | 
					 | 
				
			||||||
	})
 | 
					 | 
				
			||||||
	clientApi := http.NewServeMux()
 | 
					 | 
				
			||||||
	http.Handle("/client/", http.StripPrefix("/client", clientApi))
 | 
					 | 
				
			||||||
	clientV1Api := http.NewServeMux()
 | 
					 | 
				
			||||||
	clientApi.Handle("/v1/", http.StripPrefix("/v1", clientV1Api))
 | 
					 | 
				
			||||||
	clientV1Api.HandleFunc("/getNodes", func(resp http.ResponseWriter, req *http.Request) {
 | 
					 | 
				
			||||||
		host := getRemoteIP(req)
 | 
					 | 
				
			||||||
		nodes := mapping.GetNodes()
 | 
					 | 
				
			||||||
		if nodes == nil {
 | 
					 | 
				
			||||||
			responseWithJsonError(resp, http.StatusInternalServerError, "Unable to get nodes")
 | 
					 | 
				
			||||||
			return
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		suffix := mapping.GetSuffix(host)
 | 
					 | 
				
			||||||
		resp.Header().Set("Content-Type", "application/json")
 | 
					 | 
				
			||||||
		resp.WriteHeader(http.StatusOK)
 | 
					 | 
				
			||||||
		jsonEncoder := json.NewEncoder(resp)
 | 
					 | 
				
			||||||
		jsonEncoder.Encode(map[string]interface{}{
 | 
					 | 
				
			||||||
			"nodes":  nodes,
 | 
					 | 
				
			||||||
			"suffix": suffix,
 | 
					 | 
				
			||||||
		})
 | 
					 | 
				
			||||||
	})
 | 
					 | 
				
			||||||
	log.Println("HTTP server is running on", *listen_spec)
 | 
						log.Println("HTTP server is running on", *listen_spec)
 | 
				
			||||||
	http.ListenAndServe(*listen_spec, nil)
 | 
						http.ListenAndServe(*listen_spec, nil)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -143,14 +143,7 @@ func reload() {
 | 
				
			|||||||
	parsedFunc = &globals
 | 
						parsedFunc = &globals
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func GetMapping(ip string) string {
 | 
					func getTarget(ret starlark.Value) string {
 | 
				
			||||||
	thread := pool.Get()
 | 
					 | 
				
			||||||
	ret, err := starlark.Call(thread, (*parsedFunc)["getMapping"],
 | 
					 | 
				
			||||||
		starlark.Tuple{starlark.String(ip)}, nil)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		log.Println("Starlark execute error:", err.Error())
 | 
					 | 
				
			||||||
		return ""
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	switch r := ret.(type) {
 | 
						switch r := ret.(type) {
 | 
				
			||||||
	case starlark.String:
 | 
						case starlark.String:
 | 
				
			||||||
		return string(r)
 | 
							return string(r)
 | 
				
			||||||
@ -205,6 +198,17 @@ scriptError:
 | 
				
			|||||||
	return ""
 | 
						return ""
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func GetMapping(ip string) string {
 | 
				
			||||||
 | 
						thread := pool.Get()
 | 
				
			||||||
 | 
						ret, err := starlark.Call(thread, (*parsedFunc)["getMapping"],
 | 
				
			||||||
 | 
							starlark.Tuple{starlark.String(ip)}, nil)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Println("Starlark execute error:", err.Error())
 | 
				
			||||||
 | 
							return ""
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return getTarget(ret)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func GetNodes() (res []string) {
 | 
					func GetNodes() (res []string) {
 | 
				
			||||||
	thread := pool.Get()
 | 
						thread := pool.Get()
 | 
				
			||||||
	ret, err := starlark.Call(thread, (*parsedFunc)["getNodes"], nil, nil)
 | 
						ret, err := starlark.Call(thread, (*parsedFunc)["getNodes"], nil, nil)
 | 
				
			||||||
@ -215,12 +219,11 @@ func GetNodes() (res []string) {
 | 
				
			|||||||
	if r, ok := ret.(*starlark.List); ok {
 | 
						if r, ok := ret.(*starlark.List); ok {
 | 
				
			||||||
		res = make([]string, r.Len())
 | 
							res = make([]string, r.Len())
 | 
				
			||||||
		for i := 0; i < r.Len(); i++ {
 | 
							for i := 0; i < r.Len(); i++ {
 | 
				
			||||||
			v := r.Index(i)
 | 
								res[i] = getTarget(r.Index(i))
 | 
				
			||||||
			if s, ok := v.(starlark.String); ok {
 | 
								if res[i] == "" {
 | 
				
			||||||
				res[i] = string(s)
 | 
					 | 
				
			||||||
			} else {
 | 
					 | 
				
			||||||
				log.Println("Script returned unexpected result:",
 | 
									log.Println("Script returned unexpected result:",
 | 
				
			||||||
					ret.String())
 | 
										ret.String())
 | 
				
			||||||
 | 
									return nil
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
 | 
				
			|||||||
@ -3,7 +3,9 @@ HETZNER_FSN_1GE         = "ge-fsn1-de"
 | 
				
			|||||||
HETZNER_HEL_1GE         = "ge-hel1-fi"
 | 
					HETZNER_HEL_1GE         = "ge-hel1-fi"
 | 
				
			||||||
CLOUDCONE_LAX1_1GE		= "ge-lax1-us"
 | 
					CLOUDCONE_LAX1_1GE		= "ge-lax1-us"
 | 
				
			||||||
CLOUDCONE_LAX2_1GE		= "ge-lax2-us"
 | 
					CLOUDCONE_LAX2_1GE		= "ge-lax2-us"
 | 
				
			||||||
CLOUDCONE_LAX_LB		= (CLOUDCONE_LAX1_1GE, CLOUDCONE_LAX2_1GE)
 | 
					CLOUDCONE_LAX3_1GE		= "ge-lax3-us"
 | 
				
			||||||
 | 
					HOSTSOLUTIONS_OMR1_1GE  = "ge-omr1-ro"
 | 
				
			||||||
 | 
					CLOUDCONE_LAX_LB		= (CLOUDCONE_LAX1_1GE, CLOUDCONE_LAX2_1GE, CLOUDCONE_LAX3_1GE)
 | 
				
			||||||
default_server          = WHOLESALE_INTERNET_10GE
 | 
					default_server          = WHOLESALE_INTERNET_10GE
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CHINA_MAINLAND_SUFFIX = ".eveedge.link"
 | 
					CHINA_MAINLAND_SUFFIX = ".eveedge.link"
 | 
				
			||||||
@ -30,7 +32,7 @@ def getMapping(ip):
 | 
				
			|||||||
	return default_server
 | 
						return default_server
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def getNodes():
 | 
					def getNodes():
 | 
				
			||||||
	return ["xe-mci1-us", "ge-fsn1-de", "ge-lax1-us"]
 | 
						return [WHOLESALE_INTERNET_10GE, HETZNER_FSN_1GE, CLOUDCONE_LAX_LB, HOSTSOLUTIONS_OMR1_1GE]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def getSuffix(ip):
 | 
					def getSuffix(ip):
 | 
				
			||||||
	info = geoLookup(ip)
 | 
						info = geoLookup(ip)
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										9
									
								
								utils/BUILD.bazel
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								utils/BUILD.bazel
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,9 @@
 | 
				
			|||||||
 | 
					load("@io_bazel_rules_go//go:def.bzl", "go_library")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					go_library(
 | 
				
			||||||
 | 
					    name = "go_default_library",
 | 
				
			||||||
 | 
					    srcs = ["utils.go"],
 | 
				
			||||||
 | 
					    importpath = "git.eve.moe/jackyyf/navigator/utils",
 | 
				
			||||||
 | 
					    visibility = ["//visibility:public"],
 | 
				
			||||||
 | 
					    deps = ["@com_github_ipipdotnet_ipdb_go//:go_default_library"],
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
							
								
								
									
										67
									
								
								utils/utils.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										67
									
								
								utils/utils.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,67 @@
 | 
				
			|||||||
 | 
					package utils
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"encoding/json"
 | 
				
			||||||
 | 
						"github.com/ipipdotnet/ipdb-go"
 | 
				
			||||||
 | 
						"net"
 | 
				
			||||||
 | 
						"net/http"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						remoteAddrHeader = "X-NAV-REMOTE-IP"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type errorMessage struct {
 | 
				
			||||||
 | 
						Error string `json:"error"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func ResponseWithError(resp http.ResponseWriter, statusCode int, message string) {
 | 
				
			||||||
 | 
						resp.Header().Set("Content-Type", "text/plain")
 | 
				
			||||||
 | 
						resp.WriteHeader(statusCode)
 | 
				
			||||||
 | 
						resp.Write([]byte("error: " + message))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func ResponseWithJsonError(resp http.ResponseWriter, statusCode int, message string) {
 | 
				
			||||||
 | 
						resp.Header().Set("Content-Type", "application/json")
 | 
				
			||||||
 | 
						resp.WriteHeader(statusCode)
 | 
				
			||||||
 | 
						encoder := json.NewEncoder(resp)
 | 
				
			||||||
 | 
						err := encoder.Encode(&errorMessage{
 | 
				
			||||||
 | 
							Error: message,
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							// This should never happen
 | 
				
			||||||
 | 
							panic("json marshal failed, check code")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func GetRemoteIP(req *http.Request) string {
 | 
				
			||||||
 | 
						if addr := req.Header.Get(remoteAddrHeader); addr != "" {
 | 
				
			||||||
 | 
							if net.ParseIP(addr).To4() == nil {
 | 
				
			||||||
 | 
								return ""
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return addr
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						host, _, err := net.SplitHostPort(req.RemoteAddr)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return ""
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if net.ParseIP(host).To4() == nil {
 | 
				
			||||||
 | 
							return ""
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return host
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func BuildLocation(info *ipdb.CityInfo) string {
 | 
				
			||||||
 | 
						ret := ""
 | 
				
			||||||
 | 
						if info.CountryName != "" {
 | 
				
			||||||
 | 
							ret += info.CountryName + " "
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if info.RegionName != "" {
 | 
				
			||||||
 | 
							ret += info.RegionName + " "
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if info.CityName != "" {
 | 
				
			||||||
 | 
							ret += info.CityName + " "
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return strings.TrimSpace(ret)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Reference in New Issue
	
	Block a user