kythe.io@v0.0.68-0.20240422202219-7225dbc01741/kythe/go/serving/api/api.go (about) 1 /* 2 * Copyright 2015 The Kythe Authors. All rights reserved. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 // Package api provides a union of the filetree, xrefs, and graph interfaces 18 // and a command-line flag parser. 19 package api // import "kythe.io/kythe/go/serving/api" 20 21 import ( 22 "context" 23 "flag" 24 "fmt" 25 "os" 26 "strings" 27 28 "kythe.io/kythe/go/services/filetree" 29 "kythe.io/kythe/go/services/graph" 30 "kythe.io/kythe/go/services/xrefs" 31 ftsrv "kythe.io/kythe/go/serving/filetree" 32 gsrv "kythe.io/kythe/go/serving/graph" 33 "kythe.io/kythe/go/serving/identifiers" 34 xsrv "kythe.io/kythe/go/serving/xrefs" 35 "kythe.io/kythe/go/storage/leveldb" 36 "kythe.io/kythe/go/storage/table" 37 38 ftpb "kythe.io/kythe/proto/filetree_go_proto" 39 gpb "kythe.io/kythe/proto/graph_go_proto" 40 ipb "kythe.io/kythe/proto/identifier_go_proto" 41 xpb "kythe.io/kythe/proto/xref_go_proto" 42 ) 43 44 // Interface is a union of the xrefs and filetree interfaces. 45 type Interface interface { 46 xrefs.Service 47 graph.Service 48 filetree.Service 49 identifiers.Service 50 51 // Close releases the underlying resources for the API. 52 Close(context.Context) error 53 } 54 55 const ( 56 // CommonDefault is the common Kythe default API specification for Flag 57 CommonDefault = "https://xrefs-dot-kythe-repo.appspot.com" 58 59 // CommonFlagUsage is the common Kythe usage description used for Flag 60 CommonFlagUsage = "Backing API specification (e.g. JSON HTTP server: https://xrefs-dot-kythe-repo.appspot.com or local serving table path: /var/kythe_serving)" 61 ) 62 63 // Flag defines an api Interface flag with specified name, default value, and 64 // usage description. The return value is the address of an Interface variable 65 // that stores the value of the flag. 66 func Flag(name, value, usage string) *Interface { 67 val := &apiFlag{} 68 val.Set(value) 69 flag.Var(val, name, usage) 70 return &val.api 71 } 72 73 // ParseSpec parses the given specification and returns an opened handle to an 74 // API Interface. The following formats are currently supported: 75 // - http:// URL pointed at a JSON web API 76 // - https:// URL pointed at a JSON web API 77 // - local path to a LevelDB serving table 78 func ParseSpec(apiSpec string) (Interface, error) { 79 api := &apiCloser{} 80 if strings.HasPrefix(apiSpec, "http://") || strings.HasPrefix(apiSpec, "https://") { 81 api.xs = xrefs.WebClient(apiSpec) 82 api.gs = graph.WebClient(apiSpec) 83 api.ft = filetree.WebClient(apiSpec) 84 api.id = identifiers.WebClient(apiSpec) 85 } else if _, err := os.Stat(apiSpec); err == nil { 86 db, err := leveldb.Open(apiSpec, nil) 87 if err != nil { 88 return nil, fmt.Errorf("error opening local DB at %q: %v", apiSpec, err) 89 } 90 api.closer = func(ctx context.Context) error { return db.Close(ctx) } 91 92 ctx := context.Background() 93 api.xs = xsrv.NewService(ctx, db) 94 api.gs = gsrv.NewService(ctx, db) 95 tbl := &table.KVProto{db} 96 api.ft = &ftsrv.Table{tbl, true} 97 api.id = &identifiers.Table{tbl} 98 } else { 99 return nil, fmt.Errorf("unknown API spec format: %q", apiSpec) 100 } 101 return api, nil 102 } 103 104 type apiFlag struct { 105 spec string 106 api Interface 107 } 108 109 // Set implements part of the flag.Value interface. 110 func (f *apiFlag) Set(spec string) error { 111 api, err := ParseSpec(spec) 112 if err != nil { 113 return err 114 } 115 f.spec = spec 116 f.api = api 117 return nil 118 } 119 120 // String implements part of the flag.Value interface. 121 func (f *apiFlag) String() string { return f.spec } 122 123 // apiCloser implements Interface 124 type apiCloser struct { 125 xs xrefs.Service 126 gs graph.Service 127 ft filetree.Service 128 id identifiers.Service 129 130 closer func(context.Context) error 131 } 132 133 // Close implements part of Interface. 134 func (api apiCloser) Close(ctx context.Context) error { 135 if api.closer != nil { 136 return api.closer(ctx) 137 } 138 return nil 139 } 140 141 // Nodes implements part of the graph Service interface. 142 func (api apiCloser) Nodes(ctx context.Context, req *gpb.NodesRequest) (*gpb.NodesReply, error) { 143 return api.gs.Nodes(ctx, req) 144 } 145 146 // Edges implements part of the graph Service interface. 147 func (api apiCloser) Edges(ctx context.Context, req *gpb.EdgesRequest) (*gpb.EdgesReply, error) { 148 return api.gs.Edges(ctx, req) 149 } 150 151 // Decorations implements part of the xrefs Service interface. 152 func (api apiCloser) Decorations(ctx context.Context, req *xpb.DecorationsRequest) (*xpb.DecorationsReply, error) { 153 return api.xs.Decorations(ctx, req) 154 } 155 156 // CrossReferences implements part of the xrefs Service interface. 157 func (api apiCloser) CrossReferences(ctx context.Context, req *xpb.CrossReferencesRequest) (*xpb.CrossReferencesReply, error) { 158 return api.xs.CrossReferences(ctx, req) 159 } 160 161 // Documentation implements part of the xrefs Service interface. 162 func (api apiCloser) Documentation(ctx context.Context, req *xpb.DocumentationRequest) (*xpb.DocumentationReply, error) { 163 return api.xs.Documentation(ctx, req) 164 } 165 166 // Directory implements part of the filetree Service interface. 167 func (api apiCloser) Directory(ctx context.Context, req *ftpb.DirectoryRequest) (*ftpb.DirectoryReply, error) { 168 return api.ft.Directory(ctx, req) 169 } 170 171 // CorpusRoots implements part of the filetree Service interface. 172 func (api apiCloser) CorpusRoots(ctx context.Context, req *ftpb.CorpusRootsRequest) (*ftpb.CorpusRootsReply, error) { 173 return api.ft.CorpusRoots(ctx, req) 174 } 175 176 // Find implements part of the identifiers Service interface. 177 func (api apiCloser) Find(ctx context.Context, req *ipb.FindRequest) (*ipb.FindReply, error) { 178 return api.id.Find(ctx, req) 179 }